diff --git a/Cargo.lock b/Cargo.lock index 5c6ed2c94..a95cee548 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,13 +322,15 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.29.2" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +checksum = "4e99ff7289b20a7385f66a0feda78af2fc119d28fb56aea8886a9cd0a4abdd75" dependencies = [ "bech32", - "bitcoin_hashes 0.11.0", - "secp256k1 0.24.3", + "bitcoin-private", + "bitcoin_hashes 0.12.0", + "hex_lit", + "secp256k1 0.27.0", "serde", ] @@ -381,6 +383,12 @@ dependencies = [ "spin 0.7.1", ] +[[package]] +name = "bitcoin-private" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" + [[package]] name = "bitcoin_hashes" version = "0.7.6" @@ -389,18 +397,20 @@ checksum = "b375d62f341cef9cd9e77793ec8f1db3fc9ce2e4d57e982c8fe697a2c16af3b6" [[package]] name = "bitcoin_hashes" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" dependencies = [ + "bitcoin-private", "serde", ] [[package]] name = "bitcoincore-rpc" -version = "0.16.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=bde02d7fbf031df7d3a49946ec0e7f1abde34e58#bde02d7fbf031df7d3a49946ec0e7f1abde34e58" +version = "0.17.0" +source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=7bd815f1e1ae721404719ee8e6867064b7c68494#7bd815f1e1ae721404719ee8e6867064b7c68494" dependencies = [ + "bitcoin-private", "bitcoincore-rpc-json", "jsonrpc", "log", @@ -410,10 +420,11 @@ dependencies = [ [[package]] name = "bitcoincore-rpc-json" -version = "0.16.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=bde02d7fbf031df7d3a49946ec0e7f1abde34e58#bde02d7fbf031df7d3a49946ec0e7f1abde34e58" +version = "0.17.0" +source = "git+https://github.com/rust-bitcoin/rust-bitcoincore-rpc?rev=7bd815f1e1ae721404719ee8e6867064b7c68494#7bd815f1e1ae721404719ee8e6867064b7c68494" dependencies = [ - "bitcoin 0.29.2", + "bitcoin 0.30.1", + "bitcoin-private", "serde", "serde_json", ] @@ -1968,6 +1979,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "hmac" version = "0.8.1" @@ -2318,9 +2335,9 @@ dependencies = [ [[package]] name = "jsonrpc" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8d6b3f301ba426b30feca834a2a18d48d5b54e5065496b5c1b05537bee3639" +checksum = "8128f36b47411cd3f044be8c1f5cc0c9e24d1d1bfdc45f0a57897b32513053f2" dependencies = [ "base64 0.13.1", "serde", @@ -4419,9 +4436,18 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ - "bitcoin_hashes 0.11.0", - "rand 0.8.5", "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "bitcoin_hashes 0.12.0", + "rand 0.8.5", + "secp256k1-sys 0.8.1", "serde", ] @@ -4442,6 +4468,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -6090,7 +6125,7 @@ dependencies = [ "parity-scale-codec", "rocksdb", "runtime", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "serde", "serde_json", "serial_test 0.9.0", diff --git a/faucet/src/http.rs b/faucet/src/http.rs index c41fffe76..87baa1522 100644 --- a/faucet/src/http.rs +++ b/faucet/src/http.rs @@ -225,7 +225,7 @@ struct GetSignatureData { } async fn ensure_signature_exists(auth_url: &str, account_id: &AccountId) -> Result<(), Error> { - let account_id = runtime::sp_core::crypto::AccountId32::from(account_id.0); + let account_id = account_id.to_sp_core_account_id(); reqwest::get(Url::parse(auth_url)?.join(&account_id.to_ss58check_with_version(SS58_PREFIX.into()))?) .await? .json::() @@ -386,7 +386,8 @@ mod tests { }; use kv::{Config, Store}; use runtime::{ - integration::*, AccountId, BtcPublicKey, FixedPointNumber, FixedU128, OraclePallet, VaultRegistryPallet, + integration::*, utils::account_id::AccountId32, AccountId, BtcPublicKey, FixedPointNumber, FixedU128, + OraclePallet, VaultRegistryPallet, }; use sp_keyring::AccountKeyring; @@ -421,7 +422,7 @@ mod tests { .into_iter() .map(move |currency_id| (account_id.clone().into(), 1 << 60, 0, currency_id)) }) - .collect::>(), + .collect::>(), ) .await .expect("Should endow accounts"); diff --git a/runtime/src/rpc.rs b/runtime/src/rpc.rs index 6f3960be6..8fbd3cbce 100644 --- a/runtime/src/rpc.rs +++ b/runtime/src/rpc.rs @@ -85,7 +85,7 @@ impl InterBtcParachain { signer: InterBtcSigner, shutdown_tx: ShutdownSender, ) -> Result { - let account_id = signer.account_id().clone(); + let account_id = signer.account_id.clone().0; let api = OnlineClient::from_rpc_client(Arc::new(rpc_client)).await?; let runtime_version = api.rpc().runtime_version(None).await?; @@ -125,7 +125,7 @@ impl InterBtcParachain { api: Arc::new(api), nonce: Arc::new(RwLock::new(0)), signer, - account_id, + account_id: (*account_id).clone().into(), shutdown_tx, fee_rate_update_tx, native_currency_id, diff --git a/runtime/src/tests.rs b/runtime/src/tests.rs index 063d3cdfd..bda0b3c80 100644 --- a/runtime/src/tests.rs +++ b/runtime/src/tests.rs @@ -8,7 +8,8 @@ use super::{ VaultRegistryPallet, KBTC, KINT, KSM, }; use crate::{ - integration::*, utils_accountid::AccountId32, FeedValuesEvent, OracleKey, RuntimeCurrencyInfo, VaultId, H160, U256, + integration::*, utils::account_id::AccountId32, FeedValuesEvent, OracleKey, RuntimeCurrencyInfo, VaultId, H160, + U256, }; use module_bitcoin::{formatter::TryFormat, types::BlockBuilder}; pub use primitives::CurrencyId::ForeignAsset; diff --git a/runtime/src/types.rs b/runtime/src/types.rs index b59e1ea40..a45028457 100644 --- a/runtime/src/types.rs +++ b/runtime/src/types.rs @@ -1,5 +1,8 @@ -pub use crate::utils::{account_id as utils_accountid, multi_signature}; -use crate::{metadata, utils::signer::PairSigner, Config, InterBtcRuntime, RuntimeCurrencyInfo}; +use crate::{ + metadata, + utils::{account_id::AccountId32, signer::PairSigner}, + Config, InterBtcRuntime, RuntimeCurrencyInfo, +}; pub use currency_id::CurrencyIdExt; pub use h256_le::RichH256Le; pub use metadata_aliases::*; @@ -13,8 +16,8 @@ pub use sp_core::sr25519::Pair as KeyPair; pub use subxt; use subxt::storage::{address::Yes, Address}; -pub type AccountId = utils_accountid::AccountId32; -pub type MultiSignature = multi_signature::MultiSignature; +pub type AccountId = AccountId32; +pub type MultiSignature = sp_runtime::MultiSignature; pub type Balance = primitives::Balance; pub type Index = u32; pub type BlockNumber = u32; @@ -211,9 +214,10 @@ pub trait PrettyPrint { mod account_id { use super::*; + use sp_core::crypto::Ss58Codec; impl PrettyPrint for AccountId { fn pretty_print(&self) -> String { - self.to_ss58check() + self.0.to_ss58check() } } } diff --git a/runtime/src/utils/account_id.rs b/runtime/src/utils/account_id.rs index 700b515c2..b8d0f0eda 100644 --- a/runtime/src/utils/account_id.rs +++ b/runtime/src/utils/account_id.rs @@ -1,15 +1,15 @@ -//! The "default" Substrate/Polkadot AccountId. This is used in codegen, as well as signing related bits. -//! This doesn't contain much functionality itself, but is easy to convert to/from an `sp_core::AccountId32`. -//! The `sp_core::AccountId32` doesn't contain EncodeAsType and DecodeAsType traits hence added a -//! custom implementation. +//! The `AccountId32` type is a wrapper around `sp_core::crypto::AccountId32` with added functionality +//! and convenience methods. It is designed for working with account IDs in the context of +//! Substrate-based blockchains. This wrapper is necessary because the `scale_encode::EncodeAsType` and +//! `scale_decode::DecodeAsType` traits are not implemented for `sp_core::crypto::AccountId32`, +//! but they are required for the latest version of the `subxt` crate. use base58::{FromBase58, ToBase58}; -use blake2::{Blake2b512, Digest}; use codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; +use sp_core::crypto::{AccountId32 as Sp_AccountId32, Ss58Codec}; use std::convert::TryInto; -/// A 32-byte cryptographic identifier. This is a simplified version of Substrate's -/// `sp_core::crypto::AccountId32`. To obtain more functionality, convert this into -/// that type. +use subxt::utils::Static; + #[derive( Hash, Clone, @@ -22,107 +22,35 @@ use std::convert::TryInto; Debug, scale_encode::EncodeAsType, scale_decode::DecodeAsType, - Default, )] -pub struct AccountId32(pub [u8; 32]); - -impl AsRef<[u8]> for AccountId32 { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsRef<[u8; 32]> for AccountId32 { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl From<[u8; 32]> for AccountId32 { - fn from(x: [u8; 32]) -> Self { - AccountId32(x) - } -} +pub struct AccountId32(pub Static); impl AccountId32 { pub fn new(value: [u8; 32]) -> Self { - AccountId32(value) - } - // Return the ss58-check string for this key. Adapted from `sp_core::crypto`. - pub fn to_ss58check(&self) -> String { - // We mask out the upper two bits of the ident - SS58 Prefix currently only supports 14-bits - let ident: u16 = crate::SS58_PREFIX & 0b0011_1111_1111_1111; - let mut v = match ident { - 0..=63 => vec![ident as u8], - 64..=16_383 => { - // upper six bits of the lower byte(!) - let first = ((ident & 0b0000_0000_1111_1100) as u8) >> 2; - // lower two bits of the lower byte in the high pos, - // lower bits of the upper byte in the low pos - let second = ((ident >> 8) as u8) | ((ident & 0b0000_0000_0000_0011) as u8) << 6; - vec![first | 0b01000000, second] - } - _ => unreachable!("masked out the upper two bits; qed"), - }; - v.extend::<&[u8]>(self.as_ref()); - let r = ss58hash(&v); - v.extend(&r[0..2]); - v.to_base58() + AccountId32(Static(value.into())) } - // This isn't strictly needed, but to give our AccountId32 a little more usefulness, we also - // implement the logic needed to decode an AccountId32 from an SS58 encoded string. This is exposed - // via a `FromStr` impl. - fn from_ss58check(s: &str) -> Result { - const CHECKSUM_LEN: usize = 2; - let body_len = 32; - - let data = s.from_base58().map_err(|_| FromSs58Error::BadBase58)?; - if data.len() < 2 { - return Err(FromSs58Error::BadLength); - } - let prefix_len = match data[0] { - 0..=63 => 1, - 64..=127 => 2, - _ => return Err(FromSs58Error::InvalidPrefix), - }; - if data.len() != prefix_len + body_len + CHECKSUM_LEN { - return Err(FromSs58Error::BadLength); - } - let hash = ss58hash(&data[0..body_len + prefix_len]); - let checksum = &hash[0..CHECKSUM_LEN]; - if data[body_len + prefix_len..body_len + prefix_len + CHECKSUM_LEN] != *checksum { - // Invalid checksum. - return Err(FromSs58Error::InvalidChecksum); - } - let result = data[prefix_len..body_len + prefix_len] - .try_into() - .map_err(|_| FromSs58Error::BadLength)?; - Ok(AccountId32(result)) + pub fn to_sp_core_account_id(&self) -> Sp_AccountId32 { + let account_id = self.0.clone(); + (*account_id).clone().into() } } -/// An error obtained from trying to interpret an SS58 encoded string into an AccountId32 -#[derive(thiserror::Error, Clone, Copy, Eq, PartialEq, Debug)] -#[allow(missing_docs)] -pub enum FromSs58Error { - #[error("Base 58 requirement is violated")] - BadBase58, - #[error("Length is bad")] - BadLength, - #[error("Invalid checksum")] - InvalidChecksum, - #[error("Invalid SS58 prefix byte.")] - InvalidPrefix, +impl std::fmt::Display for AccountId32 { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let wp_accountid = self.clone(); + let sp_accountid = wp_accountid.0; + let ss58_checks = sp_accountid.to_ss58check(); + write!(f, "{}", ss58_checks) + } } -// We do this just to get a checksum to help verify the validity of the address in to_ss58check -fn ss58hash(data: &[u8]) -> Vec { - const PREFIX: &[u8] = b"SS58PRE"; - let mut ctx = Blake2b512::new(); - ctx.update(PREFIX); - ctx.update(data); - ctx.finalize().to_vec() +impl std::str::FromStr for AccountId32 { + type Err = sp_core::crypto::PublicError; + fn from_str(s: &str) -> Result { + let account_id = Sp_AccountId32::from_ss58check(s)?; + Ok(AccountId32(Static(account_id))) + } } impl Serialize for AccountId32 { @@ -130,7 +58,7 @@ impl Serialize for AccountId32 { where S: serde::Serializer, { - serializer.serialize_str(&self.to_ss58check()) + serializer.serialize_str(self.clone().0.to_ss58check().as_str()) } } @@ -139,64 +67,45 @@ impl<'de> Deserialize<'de> for AccountId32 { where D: serde::Deserializer<'de>, { - AccountId32::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| serde::de::Error::custom(format!("{e:?}"))) - } -} - -impl std::fmt::Display for AccountId32 { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -impl std::str::FromStr for AccountId32 { - type Err = FromSs58Error; - fn from_str(s: &str) -> Result { - AccountId32::from_ss58check(s) + let account_id = Sp_AccountId32::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; + Ok(AccountId32(Static(account_id))) } } impl From for AccountId32 { fn from(value: sp_runtime::AccountId32) -> Self { - Self(value.into()) + AccountId32(Static(value.into())) } } impl From for AccountId32 { fn from(value: sp_core::sr25519::Public) -> Self { - let acc: sp_runtime::AccountId32 = value.into(); - acc.into() + let account_id: Sp_AccountId32 = value.into(); + account_id.into() } } impl From for AccountId32 { fn from(value: sp_core::ed25519::Public) -> Self { - let acc: sp_runtime::AccountId32 = value.into(); - acc.into() + let account_id: Sp_AccountId32 = value.into(); + account_id.into() } } impl From for AccountId32 { fn from(account: sp_keyring::Sr25519Keyring) -> Self { let account = account.to_account_id(); - AccountId32(account.into()) + account.into() } } -#[cfg(test)] -mod tests { - use super::*; - use crate::SS58_PREFIX; - use sp_core::crypto::Ss58Codec; - use sp_keyring::AccountKeyring; - use sp_runtime::AccountId32 as SpAccountId; +impl Default for AccountId32 { + fn default() -> Self { + AccountId32(Static([0; 32].into())) + } +} - #[test] - fn test_alice_account_conversion_to_ss58() { - let alice_utils_account_id: AccountId32 = AccountKeyring::Alice.to_account_id().into(); - let alice_sp_account_id: SpAccountId = AccountKeyring::Alice.to_account_id(); - assert_eq!( - alice_sp_account_id.to_ss58check_with_version(SS58_PREFIX.into()), - alice_utils_account_id.to_ss58check() - ); +impl From<[u8; 32]> for AccountId32 { + fn from(x: [u8; 32]) -> Self { + AccountId32(Static(x.into())) } } diff --git a/runtime/src/utils/mod.rs b/runtime/src/utils/mod.rs index 133a16096..6b8a698c6 100644 --- a/runtime/src/utils/mod.rs +++ b/runtime/src/utils/mod.rs @@ -1,3 +1,2 @@ pub mod account_id; -pub mod multi_signature; pub mod signer; diff --git a/runtime/src/utils/multi_signature.rs b/runtime/src/utils/multi_signature.rs deleted file mode 100644 index 5f7f2794e..000000000 --- a/runtime/src/utils/multi_signature.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! The "default" Substrate/Polkadot Signature type. This is used in codegen, as well as signing related bits. -//! This doesn't contain much functionality itself, but is easy to convert to/from an `sp_runtime::MultiSignature` -//! Custom implementation needed because as it feature gated by subxt `substrate-compat` feature -//! flag. -use codec::{Decode, Encode}; - -/// Signature container that can store known signature types. This is a simplified version of -/// `sp_runtime::MultiSignature`. To obtain more functionality, convert this into that type. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] -pub enum MultiSignature { - /// An Ed25519 signature. - Ed25519([u8; 64]), - /// An Sr25519 signature. - Sr25519([u8; 64]), - /// An ECDSA/SECP256k1 signature (a 512-bit value, plus 8 bits for recovery ID). - Ecdsa([u8; 65]), -} - -impl From for MultiSignature { - fn from(value: sp_runtime::MultiSignature) -> Self { - match value { - sp_runtime::MultiSignature::Ed25519(s) => Self::Ed25519(s.0), - sp_runtime::MultiSignature::Sr25519(s) => Self::Sr25519(s.0), - sp_runtime::MultiSignature::Ecdsa(s) => Self::Ecdsa(s.0), - } - } -} - -impl From for MultiSignature { - fn from(value: sp_core::ed25519::Signature) -> Self { - let sig: sp_runtime::MultiSignature = value.into(); - sig.into() - } -} - -impl From for MultiSignature { - fn from(value: sp_core::sr25519::Signature) -> Self { - let sig: sp_runtime::MultiSignature = value.into(); - sig.into() - } -} - -impl From for MultiSignature { - fn from(value: sp_core::ecdsa::Signature) -> Self { - let sig: sp_runtime::MultiSignature = value.into(); - sig.into() - } -} diff --git a/runtime/src/utils/signer.rs b/runtime/src/utils/signer.rs index c5e030a45..e5ec06826 100644 --- a/runtime/src/utils/signer.rs +++ b/runtime/src/utils/signer.rs @@ -14,7 +14,7 @@ use subxt::tx::Signer; /// A [`Signer`] implementation that can be constructed from an [`sp_core::Pair`]. #[derive(Clone, Debug)] pub struct PairSigner { - account_id: T::AccountId, + pub account_id: T::AccountId, pub signer: Pair, } diff --git a/service/src/lib.rs b/service/src/lib.rs index aef294e69..b006e3a2c 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -82,7 +82,7 @@ impl ConnectionManager { ) -> Result<(), Error> { loop { tracing::info!("Version: {}", S::VERSION); - tracing::info!("AccountId: {}", self.signer.account_id().pretty_print()); + tracing::info!("AccountId: {}", self.signer.account_id.pretty_print()); let config = self.config.clone(); let shutdown_tx = ShutdownSender::new(); diff --git a/vault/src/delay.rs b/vault/src/delay.rs index bb58c6909..d11bce07b 100644 --- a/vault/src/delay.rs +++ b/vault/src/delay.rs @@ -50,7 +50,8 @@ impl RandomDelay for OrderedVaultsDelay { /// * `data` - the seed used as a basis for the ordering (for example, an issue_id) async fn delay(&self, seed_data: &[u8; 32]) -> Result<(), RuntimeError> { fn hash_vault(data: &[u8; 32], account_id: &AccountId) -> sha256::Hash { - let account_id: [u8; 32] = AccountId32::from(account_id.0).into(); + let account_id = account_id.0.clone(); + let account_id: [u8; 32] = (*account_id).clone().into(); let xor = data.zip(account_id).map(|(a, b)| a ^ b); sha256::Hash::hash(&xor) }