From 76a6d478e07b2cdf9e5b87a2a840e92bea8d9e12 Mon Sep 17 00:00:00 2001
From: drskalman <35698397+drskalman@users.noreply.github.com>
Date: Wed, 24 Jul 2024 05:35:58 -0400
Subject: [PATCH] Migrate BEEFY BLS crypto to  bls12-381 curve (#4931)

We are definitely going to use BLS12-381 for BEEFY and it is hard coded
in JAM's spec. This PR implements missing tests for bls12-381 crypto,
migrate BEEFY BLS crypto to bls12-381 and adapt the BEEFY primitive
tests accordingly.

---------

Co-authored-by: Davide Galassi <davxy@datawok.net>
---
 .../client/consensus/beefy/src/keystore.rs    |  22 +-
 substrate/client/keystore/src/local.rs        |  56 +---
 .../application-crypto/src/bls377.rs          |  55 ----
 .../application-crypto/src/bls381.rs          |  30 ++
 .../src/{ecdsa_bls377.rs => ecdsa_bls381.rs}  |   8 +-
 .../primitives/application-crypto/src/lib.rs  |   4 +-
 .../consensus/beefy/src/commitment.rs         |   2 +-
 .../primitives/consensus/beefy/src/lib.rs     |  12 +-
 .../primitives/consensus/beefy/src/witness.rs |   8 +-
 substrate/primitives/core/src/bls.rs          | 308 +++++++++++++-----
 substrate/primitives/core/src/lib.rs          |   2 +-
 .../primitives/core/src/paired_crypto.rs      | 100 ++++++
 substrate/primitives/core/src/testing.rs      |   2 +
 substrate/primitives/io/src/lib.rs            |  20 +-
 substrate/primitives/keystore/src/lib.rs      | 137 +++-----
 substrate/primitives/keystore/src/testing.rs  |  62 ++--
 16 files changed, 460 insertions(+), 368 deletions(-)
 delete mode 100644 substrate/primitives/application-crypto/src/bls377.rs
 rename substrate/primitives/application-crypto/src/{ecdsa_bls377.rs => ecdsa_bls381.rs} (87%)

diff --git a/substrate/client/consensus/beefy/src/keystore.rs b/substrate/client/consensus/beefy/src/keystore.rs
index 8daf3440c7d..888a11db89c 100644
--- a/substrate/client/consensus/beefy/src/keystore.rs
+++ b/substrate/client/consensus/beefy/src/keystore.rs
@@ -20,7 +20,7 @@ use log::warn;
 
 use sp_application_crypto::{key_types::BEEFY as BEEFY_KEY_TYPE, AppCrypto, RuntimeAppPublic};
 #[cfg(feature = "bls-experimental")]
-use sp_core::ecdsa_bls377;
+use sp_core::ecdsa_bls381;
 use sp_core::{ecdsa, keccak_256};
 
 use sp_keystore::KeystorePtr;
@@ -100,13 +100,13 @@ impl<AuthorityId: AuthorityIdBound> BeefyKeystore<AuthorityId> {
 			},
 
 			#[cfg(feature = "bls-experimental")]
-			ecdsa_bls377::CRYPTO_ID => {
-				let public: ecdsa_bls377::Public =
-					ecdsa_bls377::Public::try_from(public.as_slice()).unwrap();
+			ecdsa_bls381::CRYPTO_ID => {
+				let public: ecdsa_bls381::Public =
+					ecdsa_bls381::Public::try_from(public.as_slice()).unwrap();
 				let sig = store
-					.ecdsa_bls377_sign_with_keccak256(BEEFY_KEY_TYPE, &public, &message)
+					.ecdsa_bls381_sign_with_keccak256(BEEFY_KEY_TYPE, &public, &message)
 					.map_err(|e| error::Error::Keystore(e.to_string()))?
-					.ok_or_else(|| error::Error::Signature("bls377_sign()  failed".to_string()))?;
+					.ok_or_else(|| error::Error::Signature("bls381_sign()  failed".to_string()))?;
 				let sig_ref: &[u8] = sig.as_ref();
 				sig_ref.to_vec()
 			},
@@ -146,8 +146,8 @@ impl<AuthorityId: AuthorityIdBound> BeefyKeystore<AuthorityId> {
 				}),
 
 			#[cfg(feature = "bls-experimental")]
-			ecdsa_bls377::CRYPTO_ID => store
-				.ecdsa_bls377_public_keys(BEEFY_KEY_TYPE)
+			ecdsa_bls381::CRYPTO_ID => store
+				.ecdsa_bls381_public_keys(BEEFY_KEY_TYPE)
 				.drain(..)
 				.map(|pk| AuthorityId::try_from(pk.as_ref()))
 				.collect::<Result<Vec<_>, _>>()
@@ -254,9 +254,9 @@ pub mod tests {
 				AuthorityId::decode(&mut pk.as_ref()).unwrap()
 			},
 			#[cfg(feature = "bls-experimental")]
-			ecdsa_bls377::CRYPTO_ID => {
+			ecdsa_bls381::CRYPTO_ID => {
 				let pk = store
-					.ecdsa_bls377_generate_new(key_type, optional_seed.as_deref())
+					.ecdsa_bls381_generate_new(key_type, optional_seed.as_deref())
 					.ok()
 					.unwrap();
 				AuthorityId::decode(&mut pk.as_ref()).unwrap()
@@ -452,7 +452,7 @@ pub mod tests {
 	#[cfg(feature = "bls-experimental")]
 	#[test]
 	fn sign_error_for_ecdsa_n_bls() {
-		sign_error::<ecdsa_bls_crypto::AuthorityId>("bls377_sign()  failed");
+		sign_error::<ecdsa_bls_crypto::AuthorityId>("bls381_sign()  failed");
 	}
 
 	#[test]
diff --git a/substrate/client/keystore/src/local.rs b/substrate/client/keystore/src/local.rs
index 8b922c11cbc..91c52bfcd50 100644
--- a/substrate/client/keystore/src/local.rs
+++ b/substrate/client/keystore/src/local.rs
@@ -37,7 +37,7 @@ use sp_core::bandersnatch;
 }
 
 sp_keystore::bls_experimental_enabled! {
-use sp_core::{bls377, bls381, ecdsa_bls377, KeccakHasher};
+use sp_core::{bls381, ecdsa_bls381, KeccakHasher};
 }
 
 use crate::{Error, Result};
@@ -357,68 +357,42 @@ impl Keystore for LocalKeystore {
 			self.sign::<bls381::Pair>(key_type, public, msg)
 		}
 
-		fn bls377_public_keys(&self, key_type: KeyTypeId) -> Vec<bls377::Public> {
-			self.public_keys::<bls377::Pair>(key_type)
+		fn ecdsa_bls381_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa_bls381::Public> {
+			self.public_keys::<ecdsa_bls381::Pair>(key_type)
 		}
 
-		/// Generate a new pair compatible with the 'bls377' signature scheme.
+		/// Generate a new pair of paired-keys compatible with the '(ecdsa,bls381)' signature scheme.
 		///
 		/// If `[seed]` is `Some` then the key will be ephemeral and stored in memory.
-		fn bls377_generate_new(
+		fn ecdsa_bls381_generate_new(
 			&self,
 			key_type: KeyTypeId,
 			seed: Option<&str>,
-		) -> std::result::Result<bls377::Public, TraitError> {
-			self.generate_new::<bls377::Pair>(key_type, seed)
+		) -> std::result::Result<ecdsa_bls381::Public, TraitError> {
+			self.generate_new::<ecdsa_bls381::Pair>(key_type, seed)
 		}
 
-		fn bls377_sign(
+		fn ecdsa_bls381_sign(
 			&self,
 			key_type: KeyTypeId,
-			public: &bls377::Public,
+			public: &ecdsa_bls381::Public,
 			msg: &[u8],
-		) -> std::result::Result<Option<bls377::Signature>, TraitError> {
-			self.sign::<bls377::Pair>(key_type, public, msg)
+		) -> std::result::Result<Option<ecdsa_bls381::Signature>, TraitError> {
+			self.sign::<ecdsa_bls381::Pair>(key_type, public, msg)
 		}
 
-		fn ecdsa_bls377_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa_bls377::Public> {
-			self.public_keys::<ecdsa_bls377::Pair>(key_type)
-		}
-
-		/// Generate a new pair of paired-keys compatible with the '(ecdsa,bls377)' signature scheme.
-		///
-		/// If `[seed]` is `Some` then the key will be ephemeral and stored in memory.
-		fn ecdsa_bls377_generate_new(
-			&self,
-			key_type: KeyTypeId,
-			seed: Option<&str>,
-		) -> std::result::Result<ecdsa_bls377::Public, TraitError> {
-			self.generate_new::<ecdsa_bls377::Pair>(key_type, seed)
-		}
-
-		fn ecdsa_bls377_sign(
-			&self,
-			key_type: KeyTypeId,
-			public: &ecdsa_bls377::Public,
-			msg: &[u8],
-		) -> std::result::Result<Option<ecdsa_bls377::Signature>, TraitError> {
-			self.sign::<ecdsa_bls377::Pair>(key_type, public, msg)
-		}
-
-			fn ecdsa_bls377_sign_with_keccak256(
+		fn ecdsa_bls381_sign_with_keccak256(
 			&self,
 			key_type: KeyTypeId,
-			public: &ecdsa_bls377::Public,
+			public: &ecdsa_bls381::Public,
 			msg: &[u8],
-		) -> std::result::Result<Option<ecdsa_bls377::Signature>, TraitError> {
+		) -> std::result::Result<Option<ecdsa_bls381::Signature>, TraitError> {
 			 let sig = self.0
 			.read()
-			.key_pair_by_type::<ecdsa_bls377::Pair>(public, key_type)?
+			.key_pair_by_type::<ecdsa_bls381::Pair>(public, key_type)?
 			.map(|pair| pair.sign_with_hasher::<KeccakHasher>(msg));
 			Ok(sig)
 		}
-
-
 	}
 }
 
diff --git a/substrate/primitives/application-crypto/src/bls377.rs b/substrate/primitives/application-crypto/src/bls377.rs
deleted file mode 100644
index 9d346ea6183..00000000000
--- a/substrate/primitives/application-crypto/src/bls377.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-//! BLS12-377 crypto applications.
-use crate::{KeyTypeId, RuntimePublic};
-
-use alloc::vec::Vec;
-pub use sp_core::bls::bls377::*;
-
-mod app {
-	crate::app_crypto!(super, sp_core::testing::BLS377);
-}
-
-pub use app::{Pair as AppPair, Public as AppPublic, Signature as AppSignature};
-
-impl RuntimePublic for Public {
-	type Signature = Signature;
-
-	/// Dummy implementation. Returns an empty vector.
-	fn all(_key_type: KeyTypeId) -> Vec<Self> {
-		Vec::new()
-	}
-
-	fn generate_pair(key_type: KeyTypeId, seed: Option<Vec<u8>>) -> Self {
-		sp_io::crypto::bls377_generate(key_type, seed)
-	}
-
-	/// Dummy implementation. Returns `None`.
-	fn sign<M: AsRef<[u8]>>(&self, _key_type: KeyTypeId, _msg: &M) -> Option<Self::Signature> {
-		None
-	}
-
-	/// Dummy implementation. Returns `false`.
-	fn verify<M: AsRef<[u8]>>(&self, _msg: &M, _signature: &Self::Signature) -> bool {
-		false
-	}
-
-	fn to_raw_vec(&self) -> Vec<u8> {
-		sp_core::crypto::ByteArray::to_raw_vec(self)
-	}
-}
diff --git a/substrate/primitives/application-crypto/src/bls381.rs b/substrate/primitives/application-crypto/src/bls381.rs
index d990f2e14c8..d4006720ce2 100644
--- a/substrate/primitives/application-crypto/src/bls381.rs
+++ b/substrate/primitives/application-crypto/src/bls381.rs
@@ -16,6 +16,9 @@
 // limitations under the License.
 
 //! BLS12-381 crypto applications.
+use crate::{KeyTypeId, RuntimePublic};
+
+use alloc::vec::Vec;
 
 pub use sp_core::bls::bls381::*;
 
@@ -26,3 +29,30 @@ mod app {
 #[cfg(feature = "full_crypto")]
 pub use app::Pair as AppPair;
 pub use app::{Public as AppPublic, Signature as AppSignature};
+
+impl RuntimePublic for Public {
+	type Signature = Signature;
+
+	/// Dummy implementation. Returns an empty vector.
+	fn all(_key_type: KeyTypeId) -> Vec<Self> {
+		Vec::new()
+	}
+
+	fn generate_pair(key_type: KeyTypeId, seed: Option<Vec<u8>>) -> Self {
+		sp_io::crypto::bls381_generate(key_type, seed)
+	}
+
+	/// Dummy implementation. Returns `None`.
+	fn sign<M: AsRef<[u8]>>(&self, _key_type: KeyTypeId, _msg: &M) -> Option<Self::Signature> {
+		None
+	}
+
+	/// Dummy implementation. Returns `false`.
+	fn verify<M: AsRef<[u8]>>(&self, _msg: &M, _signature: &Self::Signature) -> bool {
+		false
+	}
+
+	fn to_raw_vec(&self) -> Vec<u8> {
+		sp_core::crypto::ByteArray::to_raw_vec(self)
+	}
+}
diff --git a/substrate/primitives/application-crypto/src/ecdsa_bls377.rs b/substrate/primitives/application-crypto/src/ecdsa_bls381.rs
similarity index 87%
rename from substrate/primitives/application-crypto/src/ecdsa_bls377.rs
rename to substrate/primitives/application-crypto/src/ecdsa_bls381.rs
index 443d214d677..f6c6ddd3ea2 100644
--- a/substrate/primitives/application-crypto/src/ecdsa_bls377.rs
+++ b/substrate/primitives/application-crypto/src/ecdsa_bls381.rs
@@ -15,15 +15,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! ECDSA and BLS12-377 paired crypto applications.
+//! ECDSA and BLS12-381 paired crypto applications.
 
 use crate::{KeyTypeId, RuntimePublic};
 use alloc::vec::Vec;
 
-pub use sp_core::paired_crypto::ecdsa_bls377::*;
+pub use sp_core::paired_crypto::ecdsa_bls381::*;
 
 mod app {
-	crate::app_crypto!(super, sp_core::testing::ECDSA_BLS377);
+	crate::app_crypto!(super, sp_core::testing::ECDSA_BLS381);
 }
 
 #[cfg(feature = "full_crypto")]
@@ -39,7 +39,7 @@ impl RuntimePublic for Public {
 	}
 
 	fn generate_pair(key_type: KeyTypeId, seed: Option<Vec<u8>>) -> Self {
-		sp_io::crypto::ecdsa_bls377_generate(key_type, seed)
+		sp_io::crypto::ecdsa_bls381_generate(key_type, seed)
 	}
 
 	/// Dummy implementation. Returns `None`.
diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs
index 37949d7c41d..a8eb6b786a3 100644
--- a/substrate/primitives/application-crypto/src/lib.rs
+++ b/substrate/primitives/application-crypto/src/lib.rs
@@ -47,12 +47,10 @@ pub use serde;
 #[cfg(feature = "bandersnatch-experimental")]
 pub mod bandersnatch;
 #[cfg(feature = "bls-experimental")]
-pub mod bls377;
-#[cfg(feature = "bls-experimental")]
 pub mod bls381;
 pub mod ecdsa;
 #[cfg(feature = "bls-experimental")]
-pub mod ecdsa_bls377;
+pub mod ecdsa_bls381;
 pub mod ed25519;
 pub mod sr25519;
 mod traits;
diff --git a/substrate/primitives/consensus/beefy/src/commitment.rs b/substrate/primitives/consensus/beefy/src/commitment.rs
index 8d3a6c6aa90..5d4338aca10 100644
--- a/substrate/primitives/consensus/beefy/src/commitment.rs
+++ b/substrate/primitives/consensus/beefy/src/commitment.rs
@@ -482,7 +482,7 @@ mod tests {
 		assert_eq!(
 			encoded,
 			array_bytes::hex2bytes_unchecked(
-				"046d68343048656c6c6f20576f726c642105000000000000000000000000000000000000000000000004300400000008558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba015dd1c9b2237e54baa93d232cdf83a430b58a5efbc2f86ca1bab173a315ff6f15bef161425750c028055e9a23947b73002889a8b22168628438875a8ef25d76db998a80187b50719471286f054f3b3809b77a0cd87d7fe9c1a9d5d562683e25a70610f0804e92340549a43a7159b77b0c2d6e1f8105c337a86cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a0046395a71681be3d0c2a001074884b6998c82331bd57ffa0a02cbfd02483c765b9216eab6a1fc119206236bf7971be68acaebff7400edee943240006a6096c9cfa65e9eb4e67f025c27112d14b4574fb208c439500f45cf3a8060f6cf009044f3141cce0364a7c2710a19b1bdf4abf27f86e5e3db08bddd35a7d12"
+				"046d68343048656c6c6f20576f726c642105000000000000000000000000000000000000000000000004300400000008558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba0182022df4689ef25499205f7154a1a62eb2d6d5c4a3657efed321e2c277998130d1b01a264c928afb79534cb0fa9dcf79f67ed4e6bf2de576bb936146f2fa60fa56b8651677cc764ea4fe317c62294c2a0c5966e439653eed0572fded5e2461c888518e0769718dcce9f3ff612fb89d262d6e1f8105c337a86cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a0046395a71681be3d0c2a00a90973bea76fac3a4e2d76a25ec3926d6a5a20aacee15ec0756cd268088ed5612b67b4a49349cee70bc1185078d17c7f7df9d944e8be30022d9680d0437c4ba4600d74050692e8ee9b96e37df2a39d1cb4b4af4b6a058342dd9e8c7481a3a0b8975ad8614c953e950253aa327698d842"
 			)
 		);
 	}
diff --git a/substrate/primitives/consensus/beefy/src/lib.rs b/substrate/primitives/consensus/beefy/src/lib.rs
index 020e1667cbc..6ec4a727e27 100644
--- a/substrate/primitives/consensus/beefy/src/lib.rs
+++ b/substrate/primitives/consensus/beefy/src/lib.rs
@@ -142,10 +142,10 @@ pub mod ecdsa_crypto {
 #[cfg(feature = "bls-experimental")]
 pub mod bls_crypto {
 	use super::{AuthorityIdBound, BeefyAuthorityId, Hash, RuntimeAppPublic, KEY_TYPE};
-	use sp_application_crypto::{app_crypto, bls377};
-	use sp_core::{bls377::Pair as BlsPair, crypto::Wraps, Pair as _};
+	use sp_application_crypto::{app_crypto, bls381};
+	use sp_core::{bls381::Pair as BlsPair, crypto::Wraps, Pair as _};
 
-	app_crypto!(bls377, KEY_TYPE);
+	app_crypto!(bls381, KEY_TYPE);
 
 	/// Identity of a BEEFY authority using BLS as its crypto.
 	pub type AuthorityId = Public;
@@ -184,10 +184,10 @@ pub mod bls_crypto {
 #[cfg(feature = "bls-experimental")]
 pub mod ecdsa_bls_crypto {
 	use super::{AuthorityIdBound, BeefyAuthorityId, Hash, RuntimeAppPublic, KEY_TYPE};
-	use sp_application_crypto::{app_crypto, ecdsa_bls377};
-	use sp_core::{crypto::Wraps, ecdsa_bls377::Pair as EcdsaBlsPair};
+	use sp_application_crypto::{app_crypto, ecdsa_bls381};
+	use sp_core::{crypto::Wraps, ecdsa_bls381::Pair as EcdsaBlsPair};
 
-	app_crypto!(ecdsa_bls377, KEY_TYPE);
+	app_crypto!(ecdsa_bls381, KEY_TYPE);
 
 	/// Identity of a BEEFY authority using (ECDSA,BLS) as its crypto.
 	pub type AuthorityId = Public;
diff --git a/substrate/primitives/consensus/beefy/src/witness.rs b/substrate/primitives/consensus/beefy/src/witness.rs
index cfffc94254a..f27660cc0ca 100644
--- a/substrate/primitives/consensus/beefy/src/witness.rs
+++ b/substrate/primitives/consensus/beefy/src/witness.rs
@@ -90,7 +90,7 @@ mod tests {
 	#[cfg(feature = "bls-experimental")]
 	use w3f_bls::{
 		single_pop_aggregator::SignatureAggregatorAssumingPoP, Message, SerializableToBytes,
-		Signed, TinyBLS377,
+		Signed, TinyBLS381,
 	};
 
 	type TestCommitment = Commitment<u128>;
@@ -198,7 +198,7 @@ mod tests {
 			// from signed take a function as the aggregator 
 			TestBlsSignedCommitmentWitness::from_signed::<_, _>(signed, |sigs| {
 				// we are going to aggregate the signatures here
-				let mut aggregatedsigs: SignatureAggregatorAssumingPoP<TinyBLS377> =
+				let mut aggregatedsigs: SignatureAggregatorAssumingPoP<TinyBLS381> =
 					SignatureAggregatorAssumingPoP::new(Message::new(b"", b"mock payload"));
 
 				for sig in sigs {
@@ -206,7 +206,7 @@ mod tests {
 						Some(sig) => {
 							let serialized_sig : Vec<u8> = (*sig.1).to_vec();
 							aggregatedsigs.add_signature(
-								&w3f_bls::Signature::<TinyBLS377>::from_bytes(
+								&w3f_bls::Signature::<TinyBLS381>::from_bytes(
 									serialized_sig.as_slice()
 								).unwrap()
 							);
@@ -219,7 +219,7 @@ mod tests {
 
 		// We can't use BlsSignature::try_from because it expected 112Bytes (CP (64) + BLS 48)
 		// single signature while we are having a BLS aggregated signature corresponding to no CP.
-		w3f_bls::Signature::<TinyBLS377>::from_bytes(witness.signature_accumulator.as_slice())
+		w3f_bls::Signature::<TinyBLS381>::from_bytes(witness.signature_accumulator.as_slice())
 			.unwrap();
 	}
 
diff --git a/substrate/primitives/core/src/bls.rs b/substrate/primitives/core/src/bls.rs
index a86f67844da..f721a6ae08d 100644
--- a/substrate/primitives/core/src/bls.rs
+++ b/substrate/primitives/core/src/bls.rs
@@ -39,22 +39,22 @@ use w3f_bls::{
 pub mod bls377 {
 	pub use super::{PUBLIC_KEY_SERIALIZED_SIZE, SIGNATURE_SERIALIZED_SIZE};
 	use crate::crypto::CryptoTypeId;
-	use w3f_bls::TinyBLS377;
+	pub(crate) use w3f_bls::TinyBLS377 as BlsEngine;
 
 	/// 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;
+	pub type Bls377Tag = BlsEngine;
 
 	/// BLS12-377 key pair.
-	pub type Pair = super::Pair<TinyBLS377>;
+	pub type Pair = super::Pair<BlsEngine>;
 	/// BLS12-377 public key.
-	pub type Public = super::Public<TinyBLS377>;
+	pub type Public = super::Public<BlsEngine>;
 	/// BLS12-377 signature.
-	pub type Signature = super::Signature<TinyBLS377>;
+	pub type Signature = super::Signature<BlsEngine>;
 
-	impl super::HardJunctionId for TinyBLS377 {
+	impl super::HardJunctionId for BlsEngine {
 		const ID: &'static str = "BLS12377HDKD";
 	}
 }
@@ -63,19 +63,22 @@ pub mod bls377 {
 pub mod bls381 {
 	pub use super::{PUBLIC_KEY_SERIALIZED_SIZE, SIGNATURE_SERIALIZED_SIZE};
 	use crate::crypto::CryptoTypeId;
-	use w3f_bls::TinyBLS381;
+	pub(crate) use w3f_bls::TinyBLS381 as BlsEngine;
 
 	/// An identifier used to match public keys against BLS12-381 keys
 	pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"bls8");
 
+	#[doc(hidden)]
+	pub type Bls381Tag = BlsEngine;
+
 	/// BLS12-381 key pair.
-	pub type Pair = super::Pair<TinyBLS381>;
+	pub type Pair = super::Pair<BlsEngine>;
 	/// BLS12-381 public key.
-	pub type Public = super::Public<TinyBLS381>;
+	pub type Public = super::Public<BlsEngine>;
 	/// BLS12-381 signature.
-	pub type Signature = super::Signature<TinyBLS381>;
+	pub type Signature = super::Signature<BlsEngine>;
 
-	impl super::HardJunctionId for TinyBLS381 {
+	impl super::HardJunctionId for BlsEngine {
 		const ID: &'static str = "BLS12381HDKD";
 	}
 }
@@ -235,30 +238,46 @@ mod tests {
 	#[cfg(feature = "serde")]
 	use crate::crypto::Ss58Codec;
 	use crate::crypto::DEV_PHRASE;
-	use bls377::{Pair, Signature};
+	use bls377::Pair as Bls377Pair;
+	use bls381::Pair as Bls381Pair;
 
-	#[test]
-	fn default_phrase_should_be_used() {
+	fn default_phrase_should_be_used<E: BlsBound>() {
 		assert_eq!(
-			Pair::from_string("//Alice///password", None).unwrap().public(),
-			Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password"))
+			Pair::<E>::from_string("//Alice///password", None).unwrap().public(),
+			Pair::<E>::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password"))
 				.unwrap()
 				.public(),
 		);
 	}
 
 	#[test]
-	fn seed_and_derive_should_work() {
+	fn default_phrase_should_be_used_for_bls377() {
+		default_phrase_should_be_used::<bls377::BlsEngine>();
+	}
+
+	#[test]
+	fn default_phrase_should_be_used_for_bls381() {
+		default_phrase_should_be_used::<bls381::BlsEngine>();
+	}
+
+	fn seed_and_derive_should_work<E: BlsBound>() -> Vec<u8> {
 		let seed = array_bytes::hex2array_unchecked(
 			"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
 		);
-		let pair = Pair::from_seed(&seed);
+		let pair = Pair::<E>::from_seed(&seed);
 		// we are using hash-to-field so this is not going to work
 		// assert_eq!(pair.seed(), seed);
 		let path = vec![DeriveJunction::Hard([0u8; 32])];
 		let derived = pair.derive(path.into_iter(), None).ok().unwrap().0;
+		println!("derived is: {:?}", array_bytes::bytes2hex("", derived.to_raw_vec()));
+		derived.to_raw_vec()
+	}
+
+	#[test]
+	fn seed_and_derive_should_work_for_bls377() {
+		let derived_as_raw_vector = seed_and_derive_should_work::<bls377::BlsEngine>();
 		assert_eq!(
-			derived.to_raw_vec(),
+			derived_as_raw_vector,
 			array_bytes::hex2array_unchecked::<_, 32>(
 				"3a0626d095148813cd1642d38254f1cfff7eb8cc1a2fc83b2a135377c3554c12"
 			)
@@ -266,99 +285,163 @@ mod tests {
 	}
 
 	#[test]
-	fn test_vector_should_work() {
-		let pair = Pair::from_seed(&array_bytes::hex2array_unchecked(
-			"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
-		));
+	fn seed_and_derive_should_work_for_bls381() {
+		let derived_as_raw_vector = seed_and_derive_should_work::<bls381::BlsEngine>();
+		assert_eq!(
+			derived_as_raw_vector,
+			array_bytes::hex2array_unchecked::<_, 32>(
+				"bb6ac58be00d3c7ae5608ca64180b5af628e79b58592b6067136bb46255cea27"
+			)
+		);
+	}
+
+	fn test_vector_should_work<E: BlsBound>(
+		pair: Pair<E>,
+		hex_expected_pub_key: &str,
+		hex_expected_signature: &str,
+	) {
 		let public = pair.public();
+		let public_bytes: &[u8] = public.as_ref();
+		println!("pub key is: {:?}", array_bytes::bytes2hex("", public_bytes));
 		assert_eq!(
 			public,
-			Public::unchecked_from(array_bytes::hex2array_unchecked(
-				"7a84ca8ce4c37c93c95ecee6a3c0c9a7b9c225093cf2f12dc4f69cbfb847ef9424a18f5755d5a742247d386ff2aabb806bcf160eff31293ea9616976628f77266c8a8cc1d8753be04197bd6cdd8c5c87a148f782c4c1568d599b48833fd539001e580cff64bbc71850605433fcd051f3afc3b74819786f815ffb5272030a8d03e5df61e6183f8fd8ea85f26defa83400"
-			))
+			Public::unchecked_from(array_bytes::hex2array_unchecked(hex_expected_pub_key))
 		);
 		let message = b"";
-		let signature =
-	array_bytes::hex2array_unchecked("d1e3013161991e142d8751017d4996209c2ff8a9ee160f373733eda3b4b785ba6edce9f45f87104bbe07aa6aa6eb2780aa705efb2c13d3b317d6409d159d23bdc7cdd5c2a832d1551cf49d811d49c901495e527dbd532e3a462335ce2686009104aba7bc11c5b22be78f3198d2727a0b"
-	);
-		let signature = Signature::unchecked_from(signature);
-		assert!(pair.sign(&message[..]) == signature);
+		let expected_signature_bytes = array_bytes::hex2array_unchecked(hex_expected_signature);
+
+		let expected_signature = Signature::unchecked_from(expected_signature_bytes);
+		let signature = pair.sign(&message[..]);
+		assert!(signature == expected_signature);
 		assert!(Pair::verify(&signature, &message[..], &public));
 	}
 
 	#[test]
-	fn test_vector_by_string_should_work() {
-		let pair = Pair::from_string(
+	fn test_vector_should_work_for_bls377() {
+		let pair = Bls377Pair::from_seed(&array_bytes::hex2array_unchecked(
+			"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
+		));
+		test_vector_should_work(pair,
+	    "7a84ca8ce4c37c93c95ecee6a3c0c9a7b9c225093cf2f12dc4f69cbfb847ef9424a18f5755d5a742247d386ff2aabb806bcf160eff31293ea9616976628f77266c8a8cc1d8753be04197bd6cdd8c5c87a148f782c4c1568d599b48833fd539001e580cff64bbc71850605433fcd051f3afc3b74819786f815ffb5272030a8d03e5df61e6183f8fd8ea85f26defa83400",
+	    "d1e3013161991e142d8751017d4996209c2ff8a9ee160f373733eda3b4b785ba6edce9f45f87104bbe07aa6aa6eb2780aa705efb2c13d3b317d6409d159d23bdc7cdd5c2a832d1551cf49d811d49c901495e527dbd532e3a462335ce2686009104aba7bc11c5b22be78f3198d2727a0b"
+	    )
+	}
+
+	#[test]
+	fn test_vector_should_work_for_bls381() {
+		let pair = Bls381Pair::from_seed(&array_bytes::hex2array_unchecked(
+			"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
+		));
+		test_vector_should_work(pair,
+				    "88ff6c3a32542bc85f2adf1c490a929b7fcee50faeb95af9a036349390e9b3ea7326247c4fc4ebf88050688fd6265de0806284eec09ba0949f5df05dc93a787a14509749f36e4a0981bb748d953435483740907bb5c2fe8ffd97e8509e1a038b05fb08488db628ea0638b8d48c3ddf62ed437edd8b23d5989d6c65820fc70f80fb39b486a3766813e021124aec29a566",
+	    "8c29473f44ac4f0a8ac4dc8c8da09adf9d2faa2dbe0cfdce3ce7c920714196a1b7bf48dc05048e453c161ebc2db9f44fae060b3be77e14e66d1a5262f14d3da0c3a18e650018761a7402b31abc7dd803d466bdcb71bc28c77eb73c610cbff53c00130b79116831e520a04a8ef6630e6f"
+	    )
+	}
+
+	#[test]
+	fn test_vector_by_string_should_work_for_bls377() {
+		let pair = Bls377Pair::from_string(
 			"0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
 			None,
 		)
 		.unwrap();
-		let public = pair.public();
-		assert_eq!(
-			public,
-			Public::unchecked_from(array_bytes::hex2array_unchecked(
-				"7a84ca8ce4c37c93c95ecee6a3c0c9a7b9c225093cf2f12dc4f69cbfb847ef9424a18f5755d5a742247d386ff2aabb806bcf160eff31293ea9616976628f77266c8a8cc1d8753be04197bd6cdd8c5c87a148f782c4c1568d599b48833fd539001e580cff64bbc71850605433fcd051f3afc3b74819786f815ffb5272030a8d03e5df61e6183f8fd8ea85f26defa83400"
-			))
-		);
-		let message = b"";
-		let signature =
-	array_bytes::hex2array_unchecked("d1e3013161991e142d8751017d4996209c2ff8a9ee160f373733eda3b4b785ba6edce9f45f87104bbe07aa6aa6eb2780aa705efb2c13d3b317d6409d159d23bdc7cdd5c2a832d1551cf49d811d49c901495e527dbd532e3a462335ce2686009104aba7bc11c5b22be78f3198d2727a0b"
-	);
-		let expected_signature = Signature::unchecked_from(signature);
-		println!("signature is {:?}", pair.sign(&message[..]));
-		let signature = pair.sign(&message[..]);
-		assert!(signature == expected_signature);
-		assert!(Pair::verify(&signature, &message[..], &public));
+		test_vector_should_work(pair,
+	    "7a84ca8ce4c37c93c95ecee6a3c0c9a7b9c225093cf2f12dc4f69cbfb847ef9424a18f5755d5a742247d386ff2aabb806bcf160eff31293ea9616976628f77266c8a8cc1d8753be04197bd6cdd8c5c87a148f782c4c1568d599b48833fd539001e580cff64bbc71850605433fcd051f3afc3b74819786f815ffb5272030a8d03e5df61e6183f8fd8ea85f26defa83400",
+	    "d1e3013161991e142d8751017d4996209c2ff8a9ee160f373733eda3b4b785ba6edce9f45f87104bbe07aa6aa6eb2780aa705efb2c13d3b317d6409d159d23bdc7cdd5c2a832d1551cf49d811d49c901495e527dbd532e3a462335ce2686009104aba7bc11c5b22be78f3198d2727a0b"
+	    )
 	}
+
 	#[test]
-	fn generated_pair_should_work() {
-		let (pair, _) = Pair::generate();
+	fn test_vector_by_string_should_work_for_bls381() {
+		let pair = Bls381Pair::from_string(
+			"0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
+			None,
+		)
+		.unwrap();
+		test_vector_should_work(pair,
+	    "88ff6c3a32542bc85f2adf1c490a929b7fcee50faeb95af9a036349390e9b3ea7326247c4fc4ebf88050688fd6265de0806284eec09ba0949f5df05dc93a787a14509749f36e4a0981bb748d953435483740907bb5c2fe8ffd97e8509e1a038b05fb08488db628ea0638b8d48c3ddf62ed437edd8b23d5989d6c65820fc70f80fb39b486a3766813e021124aec29a566",
+	    "8c29473f44ac4f0a8ac4dc8c8da09adf9d2faa2dbe0cfdce3ce7c920714196a1b7bf48dc05048e453c161ebc2db9f44fae060b3be77e14e66d1a5262f14d3da0c3a18e650018761a7402b31abc7dd803d466bdcb71bc28c77eb73c610cbff53c00130b79116831e520a04a8ef6630e6f"
+	    )
+	}
+
+	fn test_pair<E: BlsBound>(pair: Pair<E>) -> (String, String) {
 		let public = pair.public();
 		let message = b"Something important";
 		let signature = pair.sign(&message[..]);
 		assert!(Pair::verify(&signature, &message[..], &public));
 		assert!(!Pair::verify(&signature, b"Something else", &public));
+		let public_bytes: &[u8] = public.as_ref();
+		let signature_bytes: &[u8] = signature.as_ref();
+		(array_bytes::bytes2hex("", public_bytes), array_bytes::bytes2hex("", signature_bytes))
 	}
 
 	#[test]
-	fn seeded_pair_should_work() {
-		let pair = Pair::from_seed(b"12345678901234567890123456789012");
-		let public = pair.public();
+	fn generated_pair_should_work_for_bls377() {
+		let (pair, _) = Bls377Pair::generate();
+		test_pair(pair);
+	}
+
+	#[test]
+	fn generated_pair_should_work_for_bls381() {
+		let (pair, _) = Bls381Pair::generate();
+		test_pair(pair);
+	}
+
+	#[test]
+	fn seeded_pair_should_work_for_bls377() {
+		let pair = Bls377Pair::from_seed(b"12345678901234567890123456789012");
+		let (public, _) = test_pair(pair);
 		assert_eq!(
-			public,
-			Public::unchecked_from(
-				array_bytes::hex2array_unchecked(
-				"754d2f2bbfa67df54d7e0e951979a18a1e0f45948857752cc2bac6bbb0b1d05e8e48bcc453920bf0c4bbd5993212480112a1fb433f04d74af0a8b700d93dc957ab3207f8d071e948f5aca1a7632c00bdf6d06be05b43e2e6216dccc8a5d55a0071cb2313cfd60b7e9114619cd17c06843b352f0b607a99122f6651df8f02e1ad3697bd208e62af047ddd7b942ba80080")
-			)
+		    public,
+		    "754d2f2bbfa67df54d7e0e951979a18a1e0f45948857752cc2bac6bbb0b1d05e8e48bcc453920bf0c4bbd5993212480112a1fb433f04d74af0a8b700d93dc957ab3207f8d071e948f5aca1a7632c00bdf6d06be05b43e2e6216dccc8a5d55a0071cb2313cfd60b7e9114619cd17c06843b352f0b607a99122f6651df8f02e1ad3697bd208e62af047ddd7b942ba80080"
 		);
-		let message =
-	array_bytes::hex2bytes_unchecked("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"
-	);
-		let signature = pair.sign(&message[..]);
-		println!("Correct signature: {:?}", signature);
-		assert!(Pair::verify(&signature, &message[..], &public));
-		assert!(!Pair::verify(&signature, "Other message", &public));
 	}
 
 	#[test]
-	fn generate_with_phrase_recovery_possible() {
-		let (pair1, phrase, _) = Pair::generate_with_phrase(None);
-		let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap();
+	fn seeded_pair_should_work_for_bls381() {
+		let pair = Bls381Pair::from_seed(b"12345678901234567890123456789012");
+		let (public, _) = test_pair(pair);
+		assert_eq!(
+			public,
+		    "abe9554cc2cab7fdc391a4e07ed0f45544cf0fe235babedf553c098d37dd162d9402a0aed95c00ed01349a6017a3d864adcc9756e98b7931aa3526b1511730c9cbacf3cbe781ae5efefdb177b301bca0229a5cf87432251cd31341c9b88aea9501005fa16e814ad31a95fcc396633baf563f6306e982ddec978faa0399ba73c1c1a87fa4791b3f5bbb719c1401b2af37"
+		);
+	}
 
-		assert_eq!(pair1.public(), pair2.public());
+	fn test_recover_with_phrase<E: BlsBound>(
+		pair: Pair<E>,
+		phrase: String,
+		password: Option<&str>,
+	) {
+		let (recovered_pair, _) = Pair::from_phrase(&phrase, password).unwrap();
+
+		assert_eq!(pair.public(), recovered_pair.public());
 	}
 
 	#[test]
-	fn generate_with_password_phrase_recovery_possible() {
-		let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password"));
-		let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap();
+	fn generate_with_phrase_recovery_possible_for_bls377() {
+		let (pair, phrase, _) = Bls377Pair::generate_with_phrase(None);
+		test_recover_with_phrase(pair, phrase, None);
+	}
 
-		assert_eq!(pair1.public(), pair2.public());
+	#[test]
+	fn generate_with_phrase_recovery_possible_for_bls381() {
+		let (pair, phrase, _) = Bls381Pair::generate_with_phrase(None);
+		test_recover_with_phrase(pair, phrase, None);
 	}
 
 	#[test]
-	fn generate_with_phrase_should_be_recoverable_with_from_string() {
-		let (pair, phrase, seed) = Pair::generate_with_phrase(None);
+	fn generate_with_password_phrase_recovery_possible_for_bls377() {
+		let (pair, phrase, _) = Bls377Pair::generate_with_phrase(Some("password"));
+		test_recover_with_phrase(pair, phrase, Some("password"));
+	}
+
+	#[test]
+	fn generate_with_password_phrase_recovery_possible_for_bls381() {
+		let (pair, phrase, _) = Bls381Pair::generate_with_phrase(Some("password"));
+		test_recover_with_phrase(pair, phrase, Some("password"));
+	}
+
+	fn test_recover_from_seed_and_string<E: BlsBound>(pair: Pair<E>, phrase: String, seed: Seed) {
 		let repair_seed = Pair::from_seed_slice(seed.as_ref()).expect("seed slice is valid");
 		assert_eq!(pair.public(), repair_seed.public());
 		assert_eq!(pair.to_raw_vec(), repair_seed.to_raw_vec());
@@ -374,17 +457,37 @@ mod tests {
 	}
 
 	#[test]
-	fn password_does_something() {
-		let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password"));
-		let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap();
+	fn generate_with_phrase_should_be_recoverable_with_from_string_for_bls377() {
+		let (pair, phrase, seed) = Bls377Pair::generate_with_phrase(None);
+		test_recover_from_seed_and_string(pair, phrase, seed);
+	}
+
+	#[test]
+	fn generate_with_phrase_should_be_recoverable_with_from_string_for_bls381() {
+		let (pair, phrase, seed) = Bls381Pair::generate_with_phrase(None);
+		test_recover_from_seed_and_string(pair, phrase, seed);
+	}
+
+	fn password_does_something<E: BlsBound>() {
+		let (pair1, phrase, _) = Pair::<E>::generate_with_phrase(Some("password"));
+		let (pair2, _) = Pair::<E>::from_phrase(&phrase, None).unwrap();
 
 		assert_ne!(pair1.public(), pair2.public());
 		assert_ne!(pair1.to_raw_vec(), pair2.to_raw_vec());
 	}
 
 	#[test]
-	fn ss58check_roundtrip_works() {
-		let pair = Pair::from_seed(b"12345678901234567890123456789012");
+	fn password_does_something_for_bls377() {
+		password_does_something::<bls377::BlsEngine>();
+	}
+
+	#[test]
+	fn password_does_something_for_bls381() {
+		password_does_something::<bls381::BlsEngine>();
+	}
+
+	fn ss58check_roundtrip_works<E: BlsBound>() {
+		let pair = Pair::<E>::from_seed(b"12345678901234567890123456789012");
 		let public = pair.public();
 		let s = public.to_ss58check();
 		println!("Correct: {}", s);
@@ -393,25 +496,52 @@ mod tests {
 	}
 
 	#[test]
-	fn signature_serialization_works() {
-		let pair = Pair::from_seed(b"12345678901234567890123456789012");
+	fn ss58check_roundtrip_works_for_bls377() {
+		ss58check_roundtrip_works::<bls377::BlsEngine>();
+	}
+
+	#[test]
+	fn ss58check_roundtrip_works_for_bls381() {
+		ss58check_roundtrip_works::<bls381::BlsEngine>();
+	}
+
+	fn signature_serialization_works<E: BlsBound>() {
+		let pair = Pair::<E>::from_seed(b"12345678901234567890123456789012");
 		let message = b"Something important";
 		let signature = pair.sign(&message[..]);
 		let serialized_signature = serde_json::to_string(&signature).unwrap();
 		// Signature is 112 bytes, hexify * 2, so 224  chars + 2 quote chars
 		assert_eq!(serialized_signature.len(), 226);
 		let signature = serde_json::from_str(&serialized_signature).unwrap();
-		assert!(Pair::verify(&signature, &message[..], &pair.public()));
+		assert!(Pair::<E>::verify(&signature, &message[..], &pair.public()));
+	}
+	#[test]
+	fn signature_serialization_works_for_bls377() {
+		signature_serialization_works::<bls377::BlsEngine>();
 	}
 
 	#[test]
-	fn signature_serialization_doesnt_panic() {
-		fn deserialize_signature(text: &str) -> Result<Signature, serde_json::error::Error> {
+	fn signature_serialization_works_for_bls381() {
+		signature_serialization_works::<bls381::BlsEngine>();
+	}
+	fn signature_serialization_doesnt_panic<E: BlsBound>() {
+		fn deserialize_signature<E: BlsBound>(
+			text: &str,
+		) -> Result<Signature<E>, serde_json::error::Error> {
 			serde_json::from_str(text)
 		}
-		assert!(deserialize_signature("Not valid json.").is_err());
-		assert!(deserialize_signature("\"Not an actual signature.\"").is_err());
+		assert!(deserialize_signature::<E>("Not valid json.").is_err());
+		assert!(deserialize_signature::<E>("\"Not an actual signature.\"").is_err());
 		// Poorly-sized
-		assert!(deserialize_signature("\"abc123\"").is_err());
+		assert!(deserialize_signature::<E>("\"abc123\"").is_err());
+	}
+	#[test]
+	fn signature_serialization_doesnt_panic_for_bls377() {
+		signature_serialization_doesnt_panic::<bls377::BlsEngine>();
+	}
+
+	#[test]
+	fn signature_serialization_doesnt_panic_for_bls381() {
+		signature_serialization_doesnt_panic::<bls381::BlsEngine>();
 	}
 }
diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs
index 46503921453..bb05bebc627 100644
--- a/substrate/primitives/core/src/lib.rs
+++ b/substrate/primitives/core/src/lib.rs
@@ -83,7 +83,7 @@ pub mod sr25519;
 #[cfg(feature = "bls-experimental")]
 pub use bls::{bls377, bls381};
 #[cfg(feature = "bls-experimental")]
-pub use paired_crypto::ecdsa_bls377;
+pub use paired_crypto::{ecdsa_bls377, ecdsa_bls381};
 
 pub use self::{
 	hash::{convert_hash, H160, H256, H512},
diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs
index 57bc5b00619..bf5b2636657 100644
--- a/substrate/primitives/core/src/paired_crypto.rs
+++ b/substrate/primitives/core/src/paired_crypto.rs
@@ -126,6 +126,106 @@ pub mod ecdsa_bls377 {
 	}
 }
 
+/// ECDSA and BLS12-381 paired crypto scheme
+#[cfg(feature = "bls-experimental")]
+pub mod ecdsa_bls381 {
+	use crate::{bls381, crypto::CryptoTypeId, ecdsa};
+	#[cfg(feature = "full_crypto")]
+	use crate::{
+		crypto::{Pair as PairT, UncheckedFrom},
+		Hasher,
+	};
+
+	/// An identifier used to match public keys against BLS12-381 keys
+	pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecb8");
+
+	const PUBLIC_KEY_LEN: usize =
+		ecdsa::PUBLIC_KEY_SERIALIZED_SIZE + bls381::PUBLIC_KEY_SERIALIZED_SIZE;
+	const SIGNATURE_LEN: usize =
+		ecdsa::SIGNATURE_SERIALIZED_SIZE + bls381::SIGNATURE_SERIALIZED_SIZE;
+
+	#[doc(hidden)]
+	pub struct EcdsaBls381Tag(ecdsa::EcdsaTag, bls381::Bls381Tag);
+
+	impl super::PairedCryptoSubTagBound for EcdsaBls381Tag {}
+
+	/// (ECDSA,BLS12-381) key-pair pair.
+	pub type Pair =
+		super::Pair<ecdsa::Pair, bls381::Pair, PUBLIC_KEY_LEN, SIGNATURE_LEN, EcdsaBls381Tag>;
+
+	/// (ECDSA,BLS12-381) public key pair.
+	pub type Public = super::Public<PUBLIC_KEY_LEN, EcdsaBls381Tag>;
+
+	/// (ECDSA,BLS12-381) signature pair.
+	pub type Signature = super::Signature<SIGNATURE_LEN, EcdsaBls381Tag>;
+
+	impl super::CryptoType for Public {
+		type Pair = Pair;
+	}
+
+	impl super::CryptoType for Signature {
+		type Pair = Pair;
+	}
+
+	impl super::CryptoType for Pair {
+		type Pair = Pair;
+	}
+
+	#[cfg(feature = "full_crypto")]
+	impl Pair {
+		/// Hashes the `message` with the specified [`Hasher`] before signing with the ECDSA secret
+		/// component.
+		///
+		/// The hasher does not affect the BLS12-381 component. This generates BLS12-381 Signature
+		/// according to IETF standard.
+		pub fn sign_with_hasher<H>(&self, message: &[u8]) -> Signature
+		where
+			H: Hasher,
+			H::Out: Into<[u8; 32]>,
+		{
+			let msg_hash = H::hash(message).into();
+
+			let mut raw: [u8; SIGNATURE_LEN] = [0u8; SIGNATURE_LEN];
+			raw[..ecdsa::SIGNATURE_SERIALIZED_SIZE]
+				.copy_from_slice(self.left.sign_prehashed(&msg_hash).as_ref());
+			raw[ecdsa::SIGNATURE_SERIALIZED_SIZE..]
+				.copy_from_slice(self.right.sign(message).as_ref());
+			<Self as PairT>::Signature::unchecked_from(raw)
+		}
+
+		/// Hashes the `message` with the specified [`Hasher`] before verifying with the ECDSA
+		/// public component.
+		///
+		/// The hasher does not affect the the BLS12-381 component. This verifies whether the
+		/// BLS12-381 signature was hashed and signed according to IETF standard
+		pub fn verify_with_hasher<H>(sig: &Signature, message: &[u8], public: &Public) -> bool
+		where
+			H: Hasher,
+			H::Out: Into<[u8; 32]>,
+		{
+			let msg_hash = H::hash(message).into();
+
+			let Ok(left_pub) = public.0[..ecdsa::PUBLIC_KEY_SERIALIZED_SIZE].try_into() else {
+				return false
+			};
+			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) {
+				return false
+			}
+
+			let Ok(right_pub) = public.0[ecdsa::PUBLIC_KEY_SERIALIZED_SIZE..].try_into() else {
+				return false
+			};
+			let Ok(right_sig) = sig.0[ecdsa::SIGNATURE_SERIALIZED_SIZE..].try_into() else {
+				return false
+			};
+			bls381::Pair::verify(&right_sig, message, &right_pub)
+		}
+	}
+}
+
 /// Secure seed length.
 ///
 /// Currently only supporting sub-schemes whose seed is a 32-bytes array.
diff --git a/substrate/primitives/core/src/testing.rs b/substrate/primitives/core/src/testing.rs
index c26e23d442f..378b3416db7 100644
--- a/substrate/primitives/core/src/testing.rs
+++ b/substrate/primitives/core/src/testing.rs
@@ -33,6 +33,8 @@ pub const BLS377: KeyTypeId = KeyTypeId(*b"bls7");
 pub const BLS381: KeyTypeId = KeyTypeId(*b"bls8");
 /// Key type for (ECDSA,BLS12-377) key pair
 pub const ECDSA_BLS377: KeyTypeId = KeyTypeId(*b"ecb7");
+/// Key type for (ECDSA,BLS12-381) key pair
+pub const ECDSA_BLS381: KeyTypeId = KeyTypeId(*b"ecb8");
 
 /// Macro for exporting functions from wasm in with the expected signature for using it with the
 /// wasm executor. This is useful for tests where you need to call a function in wasm.
diff --git a/substrate/primitives/io/src/lib.rs b/substrate/primitives/io/src/lib.rs
index b39a06ed211..38cf72a0c79 100644
--- a/substrate/primitives/io/src/lib.rs
+++ b/substrate/primitives/io/src/lib.rs
@@ -108,7 +108,7 @@ use sp_core::{
 };
 
 #[cfg(feature = "bls-experimental")]
-use sp_core::{bls377, ecdsa_bls377};
+use sp_core::{bls381, ecdsa_bls381};
 
 #[cfg(feature = "std")]
 use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration};
@@ -1204,38 +1204,38 @@ pub trait Crypto {
 		Ok(pubkey.serialize())
 	}
 
-	/// Generate an `bls12-377` key for the given key type using an optional `seed` and
+	/// Generate an `bls12-381` key for the given key type using an optional `seed` and
 	/// store it in the keystore.
 	///
 	/// The `seed` needs to be a valid utf8.
 	///
 	/// Returns the public key.
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> bls377::Public {
+	fn bls381_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> bls381::Public {
 		let seed = seed.as_ref().map(|s| std::str::from_utf8(s).expect("Seed is valid utf8!"));
 		self.extension::<KeystoreExt>()
 			.expect("No `keystore` associated for the current context!")
-			.bls377_generate_new(id, seed)
-			.expect("`bls377_generate` failed")
+			.bls381_generate_new(id, seed)
+			.expect("`bls381_generate` failed")
 	}
 
-	/// Generate an `(ecdsa,bls12-377)` key for the given key type using an optional `seed` and
+	/// Generate an `(ecdsa,bls12-381)` key for the given key type using an optional `seed` and
 	/// store it in the keystore.
 	///
 	/// The `seed` needs to be a valid utf8.
 	///
 	/// Returns the public key.
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_generate(
+	fn ecdsa_bls381_generate(
 		&mut self,
 		id: KeyTypeId,
 		seed: Option<Vec<u8>>,
-	) -> ecdsa_bls377::Public {
+	) -> ecdsa_bls381::Public {
 		let seed = seed.as_ref().map(|s| std::str::from_utf8(s).expect("Seed is valid utf8!"));
 		self.extension::<KeystoreExt>()
 			.expect("No `keystore` associated for the current context!")
-			.ecdsa_bls377_generate_new(id, seed)
-			.expect("`ecdsa_bls377_generate` failed")
+			.ecdsa_bls381_generate_new(id, seed)
+			.expect("`ecdsa_bls381_generate` failed")
 	}
 
 	/// Generate a `bandersnatch` key pair for the given key type using an optional
diff --git a/substrate/primitives/keystore/src/lib.rs b/substrate/primitives/keystore/src/lib.rs
index 64f0e3ea49e..42ad2c600d0 100644
--- a/substrate/primitives/keystore/src/lib.rs
+++ b/substrate/primitives/keystore/src/lib.rs
@@ -27,7 +27,7 @@ pub mod testing;
 #[cfg(feature = "bandersnatch-experimental")]
 use sp_core::bandersnatch;
 #[cfg(feature = "bls-experimental")]
-use sp_core::{bls377, bls381, ecdsa_bls377};
+use sp_core::{bls381, ecdsa_bls381};
 use sp_core::{
 	crypto::{ByteArray, CryptoTypeId, KeyTypeId},
 	ecdsa, ed25519, sr25519,
@@ -280,13 +280,9 @@ pub trait Keystore: Send + Sync {
 	#[cfg(feature = "bls-experimental")]
 	fn bls381_public_keys(&self, id: KeyTypeId) -> Vec<bls381::Public>;
 
-	/// Returns all bls12-377 public keys for the given key type.
+	/// Returns all (ecdsa,bls12-381) paired public keys for the given key type.
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_public_keys(&self, id: KeyTypeId) -> Vec<bls377::Public>;
-
-	/// Returns all (ecdsa,bls12-377) paired public keys for the given key type.
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa_bls377::Public>;
+	fn ecdsa_bls381_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa_bls381::Public>;
 
 	/// Generate a new bls381 key pair for the given key type and an optional seed.
 	///
@@ -299,27 +295,16 @@ pub trait Keystore: Send + Sync {
 		seed: Option<&str>,
 	) -> Result<bls381::Public, Error>;
 
-	/// Generate a new bls377 key pair for the given key type and an optional seed.
-	///
-	/// Returns an `bls377::Public` key of the generated key pair or an `Err` if
-	/// something failed during key generation.
-	#[cfg(feature = "bls-experimental")]
-	fn bls377_generate_new(
-		&self,
-		key_type: KeyTypeId,
-		seed: Option<&str>,
-	) -> Result<bls377::Public, Error>;
-
-	/// Generate a new (ecdsa,bls377) key pair for the given key type and an optional seed.
+	/// Generate a new (ecdsa,bls381) key pair for the given key type and an optional seed.
 	///
-	/// Returns an `ecdsa_bls377::Public` key of the generated key pair or an `Err` if
+	/// Returns an `ecdsa_bls381::Public` key of the generated key pair or an `Err` if
 	/// something failed during key generation.
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_generate_new(
+	fn ecdsa_bls381_generate_new(
 		&self,
 		key_type: KeyTypeId,
 		seed: Option<&str>,
-	) -> Result<ecdsa_bls377::Public, Error>;
+	) -> Result<ecdsa_bls381::Public, Error>;
 
 	/// Generate a bls381 signature for a given message.
 	///
@@ -337,55 +322,39 @@ pub trait Keystore: Send + Sync {
 		msg: &[u8],
 	) -> Result<Option<bls381::Signature>, Error>;
 
-	/// Generate a bls377 signature for a given message.
-	///
-	/// Receives [`KeyTypeId`] and a [`bls377::Public`] key to be able to map
-	/// them to a private key that exists in the keystore.
-	///
-	/// Returns an [`bls377::Signature`] or `None` in case the given `key_type`
-	/// and `public` combination doesn't exist in the keystore.
-	/// An `Err` will be returned if generating the signature itself failed.
-	#[cfg(feature = "bls-experimental")]
-	fn bls377_sign(
-		&self,
-		key_type: KeyTypeId,
-		public: &bls377::Public,
-		msg: &[u8],
-	) -> Result<Option<bls377::Signature>, Error>;
-
-	/// Generate a (ecdsa,bls377) signature pair for a given message.
+	/// Generate a (ecdsa,bls381) signature pair for a given message.
 	///
-	/// Receives [`KeyTypeId`] and a [`ecdsa_bls377::Public`] key to be able to map
+	/// Receives [`KeyTypeId`] and a [`ecdsa_bls381::Public`] key to be able to map
 	/// them to a private key that exists in the keystore.
 	///
-	/// Returns an [`ecdsa_bls377::Signature`] or `None` in case the given `key_type`
+	/// Returns an [`ecdsa_bls381::Signature`] or `None` in case the given `key_type`
 	/// and `public` combination doesn't exist in the keystore.
 	/// An `Err` will be returned if generating the signature itself failed.
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign(
+	fn ecdsa_bls381_sign(
 		&self,
 		key_type: KeyTypeId,
-		public: &ecdsa_bls377::Public,
+		public: &ecdsa_bls381::Public,
 		msg: &[u8],
-	) -> Result<Option<ecdsa_bls377::Signature>, Error>;
+	) -> Result<Option<ecdsa_bls381::Signature>, Error>;
 
 	/// Hashes the `message` using keccak256 and then signs it using ECDSA
-	/// algorithm. It does not affect the behavior of BLS12-377 component. It generates
-	/// BLS12-377 Signature according to IETF standard.
+	/// algorithm. It does not affect the behavior of BLS12-381 component. It generates
+	/// BLS12-381 Signature according to IETF standard.
 	///
-	/// Receives [`KeyTypeId`] and a [`ecdsa_bls377::Public`] key to be able to map
+	/// Receives [`KeyTypeId`] and a [`ecdsa_bls381::Public`] key to be able to map
 	/// them to a private key that exists in the keystore.
 	///
-	/// Returns an [`ecdsa_bls377::Signature`] or `None` in case the given `key_type`
+	/// Returns an [`ecdsa_bls381::Signature`] or `None` in case the given `key_type`
 	/// and `public` combination doesn't exist in the keystore.
 	/// An `Err` will be returned if generating the signature itself failed.
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign_with_keccak256(
+	fn ecdsa_bls381_sign_with_keccak256(
 		&self,
 		key_type: KeyTypeId,
-		public: &ecdsa_bls377::Public,
+		public: &ecdsa_bls381::Public,
 		msg: &[u8],
-	) -> Result<Option<ecdsa_bls377::Signature>, Error>;
+	) -> Result<Option<ecdsa_bls381::Signature>, Error>;
 
 	/// Insert a new secret key.
 	fn insert(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()>;
@@ -411,8 +380,7 @@ pub trait Keystore: Send + Sync {
 	/// - ecdsa
 	/// - bandersnatch
 	/// - bls381
-	/// - bls377
-	/// - (ecdsa,bls377) paired keys
+	/// - (ecdsa,bls381) paired keys
 	///
 	/// To support more schemes you can overwrite this method.
 	///
@@ -457,18 +425,11 @@ pub trait Keystore: Send + Sync {
 				self.bls381_sign(id, &public, msg)?.map(|s| s.encode())
 			},
 			#[cfg(feature = "bls-experimental")]
-			bls377::CRYPTO_ID => {
-				let public = bls377::Public::from_slice(public)
+			ecdsa_bls381::CRYPTO_ID => {
+				let public = ecdsa_bls381::Public::from_slice(public)
 					.map_err(|_| Error::ValidationError("Invalid public key format".into()))?;
-				self.bls377_sign(id, &public, msg)?.map(|s| s.encode())
+				self.ecdsa_bls381_sign(id, &public, msg)?.map(|s| s.encode())
 			},
-			#[cfg(feature = "bls-experimental")]
-			ecdsa_bls377::CRYPTO_ID => {
-				let public = ecdsa_bls377::Public::from_slice(public)
-					.map_err(|_| Error::ValidationError("Invalid public key format".into()))?;
-				self.ecdsa_bls377_sign(id, &public, msg)?.map(|s| s.encode())
-			},
-
 			_ => return Err(Error::KeyNotSupported(id)),
 		};
 		Ok(signature)
@@ -627,13 +588,8 @@ impl<T: Keystore + ?Sized> Keystore for Arc<T> {
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_public_keys(&self, id: KeyTypeId) -> Vec<bls377::Public> {
-		(**self).bls377_public_keys(id)
-	}
-
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa_bls377::Public> {
-		(**self).ecdsa_bls377_public_keys(id)
+	fn ecdsa_bls381_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa_bls381::Public> {
+		(**self).ecdsa_bls381_public_keys(id)
 	}
 
 	#[cfg(feature = "bls-experimental")]
@@ -646,21 +602,12 @@ impl<T: Keystore + ?Sized> Keystore for Arc<T> {
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_generate_new(
+	fn ecdsa_bls381_generate_new(
 		&self,
 		key_type: KeyTypeId,
 		seed: Option<&str>,
-	) -> Result<bls377::Public, Error> {
-		(**self).bls377_generate_new(key_type, seed)
-	}
-
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_generate_new(
-		&self,
-		key_type: KeyTypeId,
-		seed: Option<&str>,
-	) -> Result<ecdsa_bls377::Public, Error> {
-		(**self).ecdsa_bls377_generate_new(key_type, seed)
+	) -> Result<ecdsa_bls381::Public, Error> {
+		(**self).ecdsa_bls381_generate_new(key_type, seed)
 	}
 
 	#[cfg(feature = "bls-experimental")]
@@ -674,33 +621,23 @@ impl<T: Keystore + ?Sized> Keystore for Arc<T> {
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_sign(
-		&self,
-		key_type: KeyTypeId,
-		public: &bls377::Public,
-		msg: &[u8],
-	) -> Result<Option<bls377::Signature>, Error> {
-		(**self).bls377_sign(key_type, public, msg)
-	}
-
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign(
+	fn ecdsa_bls381_sign(
 		&self,
 		key_type: KeyTypeId,
-		public: &ecdsa_bls377::Public,
+		public: &ecdsa_bls381::Public,
 		msg: &[u8],
-	) -> Result<Option<ecdsa_bls377::Signature>, Error> {
-		(**self).ecdsa_bls377_sign(key_type, public, msg)
+	) -> Result<Option<ecdsa_bls381::Signature>, Error> {
+		(**self).ecdsa_bls381_sign(key_type, public, msg)
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign_with_keccak256(
+	fn ecdsa_bls381_sign_with_keccak256(
 		&self,
 		key_type: KeyTypeId,
-		public: &ecdsa_bls377::Public,
+		public: &ecdsa_bls381::Public,
 		msg: &[u8],
-	) -> Result<Option<ecdsa_bls377::Signature>, Error> {
-		(**self).ecdsa_bls377_sign_with_keccak256(key_type, public, msg)
+	) -> Result<Option<ecdsa_bls381::Signature>, Error> {
+		(**self).ecdsa_bls381_sign_with_keccak256(key_type, public, msg)
 	}
 
 	fn insert(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> {
diff --git a/substrate/primitives/keystore/src/testing.rs b/substrate/primitives/keystore/src/testing.rs
index 1403e4745ff..745f42e3477 100644
--- a/substrate/primitives/keystore/src/testing.rs
+++ b/substrate/primitives/keystore/src/testing.rs
@@ -22,7 +22,7 @@ use crate::{Error, Keystore, KeystorePtr};
 #[cfg(feature = "bandersnatch-experimental")]
 use sp_core::bandersnatch;
 #[cfg(feature = "bls-experimental")]
-use sp_core::{bls377, bls381, ecdsa_bls377, KeccakHasher};
+use sp_core::{bls381, ecdsa_bls381, KeccakHasher};
 use sp_core::{
 	crypto::{ByteArray, KeyTypeId, Pair, VrfSecret},
 	ecdsa, ed25519, sr25519,
@@ -299,62 +299,38 @@ impl Keystore for MemoryKeystore {
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_public_keys(&self, key_type: KeyTypeId) -> Vec<bls377::Public> {
-		self.public_keys::<bls377::Pair>(key_type)
+	fn ecdsa_bls381_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa_bls381::Public> {
+		self.public_keys::<ecdsa_bls381::Pair>(key_type)
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_generate_new(
+	fn ecdsa_bls381_generate_new(
 		&self,
 		key_type: KeyTypeId,
 		seed: Option<&str>,
-	) -> Result<bls377::Public, Error> {
-		self.generate_new::<bls377::Pair>(key_type, seed)
+	) -> Result<ecdsa_bls381::Public, Error> {
+		self.generate_new::<ecdsa_bls381::Pair>(key_type, seed)
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn bls377_sign(
+	fn ecdsa_bls381_sign(
 		&self,
 		key_type: KeyTypeId,
-		public: &bls377::Public,
+		public: &ecdsa_bls381::Public,
 		msg: &[u8],
-	) -> Result<Option<bls377::Signature>, Error> {
-		self.sign::<bls377::Pair>(key_type, public, msg)
+	) -> Result<Option<ecdsa_bls381::Signature>, Error> {
+		self.sign::<ecdsa_bls381::Pair>(key_type, public, msg)
 	}
 
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa_bls377::Public> {
-		self.public_keys::<ecdsa_bls377::Pair>(key_type)
-	}
-
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_generate_new(
-		&self,
-		key_type: KeyTypeId,
-		seed: Option<&str>,
-	) -> Result<ecdsa_bls377::Public, Error> {
-		self.generate_new::<ecdsa_bls377::Pair>(key_type, seed)
-	}
-
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign(
-		&self,
-		key_type: KeyTypeId,
-		public: &ecdsa_bls377::Public,
-		msg: &[u8],
-	) -> Result<Option<ecdsa_bls377::Signature>, Error> {
-		self.sign::<ecdsa_bls377::Pair>(key_type, public, msg)
-	}
-
-	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign_with_keccak256(
+	fn ecdsa_bls381_sign_with_keccak256(
 		&self,
 		key_type: KeyTypeId,
-		public: &ecdsa_bls377::Public,
+		public: &ecdsa_bls381::Public,
 		msg: &[u8],
-	) -> Result<Option<ecdsa_bls377::Signature>, Error> {
+	) -> Result<Option<ecdsa_bls381::Signature>, Error> {
 		let sig = self
-			.pair::<ecdsa_bls377::Pair>(key_type, public)
+			.pair::<ecdsa_bls381::Pair>(key_type, public)
 			.map(|pair| pair.sign_with_hasher::<KeccakHasher>(msg));
 		Ok(sig)
 	}
@@ -508,13 +484,13 @@ mod tests {
 
 	#[test]
 	#[cfg(feature = "bls-experimental")]
-	fn ecdsa_bls377_sign_with_keccak_works() {
+	fn ecdsa_bls381_sign_with_keccak_works() {
 		use sp_core::testing::ECDSA_BLS377;
 
 		let store = MemoryKeystore::new();
 
 		let suri = "//Alice";
-		let pair = ecdsa_bls377::Pair::from_string(suri, None).unwrap();
+		let pair = ecdsa_bls381::Pair::from_string(suri, None).unwrap();
 
 		let msg = b"this should be a normal unhashed message not a hash of a message because bls scheme comes with its own hashing";
 
@@ -522,16 +498,16 @@ mod tests {
 		store.insert(ECDSA_BLS377, suri, pair.public().as_ref()).unwrap();
 
 		let res = store
-			.ecdsa_bls377_sign_with_keccak256(ECDSA_BLS377, &pair.public(), &msg[..])
+			.ecdsa_bls381_sign_with_keccak256(ECDSA_BLS377, &pair.public(), &msg[..])
 			.unwrap();
 
 		assert!(res.is_some());
 
 		// does not verify with default out-of-the-box verification
-		assert!(!ecdsa_bls377::Pair::verify(&res.unwrap(), &msg[..], &pair.public()));
+		assert!(!ecdsa_bls381::Pair::verify(&res.unwrap(), &msg[..], &pair.public()));
 
 		// should verify using keccak256 as hasher
-		assert!(ecdsa_bls377::Pair::verify_with_hasher::<KeccakHasher>(
+		assert!(ecdsa_bls381::Pair::verify_with_hasher::<KeccakHasher>(
 			&res.unwrap(),
 			msg,
 			&pair.public()
-- 
GitLab