no_std compatibility for subxt-signer (#1477)

* subxt-signer no-std

* impl error

* address james comments

* fix signer wasm tests

* error impl for secret uri error
This commit is contained in:
Tadeo Hepperle
2024-03-14 11:04:27 +01:00
committed by GitHub
parent 8bdd276d2f
commit 4831f816f2
18 changed files with 353 additions and 196 deletions
Generated
+14 -1
View File
@@ -2865,6 +2865,17 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "password-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
dependencies = [
"base64ct",
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "paste"
version = "1.0.14"
@@ -2887,6 +2898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest 0.10.7",
"password-hash",
]
[[package]]
@@ -4660,6 +4672,8 @@ name = "subxt-signer"
version = "0.34.0"
dependencies = [
"bip39",
"cfg-if",
"derive_more",
"getrandom",
"hex",
"hmac 0.12.1",
@@ -4674,7 +4688,6 @@ dependencies = [
"sp-core-hashing",
"sp-keyring",
"subxt",
"thiserror",
"zeroize",
]
+20 -19
View File
@@ -64,6 +64,7 @@ base58 = { version = "0.2.0" }
bitvec = { version = "1", default-features = false }
blake2 = { version = "0.10.6", default-features = false }
clap = { version = "4.5.2", features = ["derive", "cargo"] }
cfg-if = "1.0.0"
criterion = "0.4"
codec = { package = "parity-scale-codec", version = "3.6.9", default-features = false }
color-eyre = "0.6.1"
@@ -71,33 +72,33 @@ console_error_panic_hook = "0.1.7"
darling = "0.20.8"
derivative = "2.2.0"
derive_more = "0.99.17"
either = "1.10.0"
either = { version = "1.10.0", default-features = false }
frame-metadata = { version = "16.0.0", default-features = false }
futures = { version = "0.3.30", default-features = false, features = ["std"] }
getrandom = { version = "0.2", default-features = false }
hashbrown = "0.14.3"
hex = "0.4.3"
hex = { version = "0.4.3", default-features = false }
heck = "0.4.1"
impl-serde = { version = "0.4.0" }
impl-serde = { version = "0.4.0", default-features = false }
indoc = "2"
jsonrpsee = { version = "0.22" }
pretty_assertions = "1.4.0"
primitive-types = { version = "0.12.2", default-features = false, features = ["codec", "scale-info", "serde"] }
primitive-types = { version = "0.12.2", default-features = false }
proc-macro-error = "1.0.4"
proc-macro2 = "1.0.78"
quote = "1.0.35"
regex = "1.10.3"
regex = { version = "1.10.3", default-features = false }
scale-info = { version = "2.10.0", default-features = false }
scale-value = "0.14.1"
scale-bits = "0.5.0"
scale-decode = "0.11.1"
scale-encode = "0.6.0"
serde = { version = "1.0.197" }
serde_json = { version = "1.0.114" }
scale-value = { version = "0.14.1", default-features = false }
scale-bits = { version = "0.5.0", default-features = false }
scale-decode = { version = "0.11.1", default-features = false }
scale-encode = { version = "0.6.0", default-features = false }
serde = { version = "1.0.197", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.114", default-features = false }
syn = { version = "2.0.15", features = ["full", "extra-traits"] }
thiserror = "1.0.57"
tokio = { version = "1.36", default-features = false }
tracing = "0.1.40"
tracing = { version = "0.1.40", default-features = false }
tracing-wasm = "0.2.1"
tracing-subscriber = "0.3.18"
trybuild = "1.0.89"
@@ -136,21 +137,21 @@ sp-keyring = "31.0.0"
# Subxt workspace crates:
subxt = { version = "0.34.0", path = "subxt", default-features = false }
subxt-macro = { version = "0.34.0", path = "macro" }
subxt-metadata = { version = "0.34.0", path = "metadata" }
subxt-metadata = { version = "0.34.0", path = "metadata", default-features = false }
subxt-codegen = { version = "0.34.0", path = "codegen" }
subxt-signer = { version = "0.34.0", path = "signer" }
subxt-signer = { version = "0.34.0", path = "signer", default-features = false }
subxt-lightclient = { version = "0.34.0", path = "lightclient", default-features = false }
test-runtime = { path = "testing/test-runtime" }
substrate-runner = { path = "testing/substrate-runner" }
# subxt-signer deps that I expect aren't useful anywhere else:
bip39 = "2.0.0"
hmac = "0.12.1"
bip39 = { version = "2.0.0", default-features = false }
hmac = { version = "0.12.1", default-features = false }
pbkdf2 = { version = "0.12.2", default-features = false }
schnorrkel = "0.11.4"
secp256k1 = "0.28.2"
schnorrkel = { version = "0.11.4", default-features = false }
secp256k1 = { version = "0.28.2", default-features = false }
secrecy = "0.8.0"
sha2 = "0.10.8"
sha2 = { version = "0.10.8", default-features = false }
zeroize = { version = "1", default-features = false }
[profile.dev.package.smoldot-light]
+1 -1
View File
@@ -19,7 +19,7 @@ use subxt_metadata::RuntimeApiMetadata;
/// Runs for a specified runtime API trait.
/// Cases to consider:
/// ```norun
/// ```txt
/// method is:
/// None => Show pallet docs + available methods
/// Some (invalid) => Show Error + available methods
+1 -1
View File
@@ -26,7 +26,7 @@ syn = { workspace = true }
scale-info = { workspace = true }
subxt-metadata = { workspace = true }
jsonrpsee = { workspace = true, features = ["async-client", "client-ws-transport-native-tls", "http-client"], optional = true }
hex = { workspace = true }
hex = { workspace = true, features = ["std"] }
tokio = { workspace = true, features = ["rt-multi-thread"], optional = true }
thiserror = { workspace = true }
scale-typegen = { workspace = true }
+4 -100
View File
@@ -464,38 +464,14 @@ dependencies = [
"syn 2.0.48",
]
[[package]]
name = "darling"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
dependencies = [
"darling_core 0.14.4",
"darling_macro 0.14.4",
]
[[package]]
name = "darling"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
dependencies = [
"darling_core 0.20.8",
"darling_macro 0.20.8",
]
[[package]]
name = "darling_core"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
"darling_core",
"darling_macro",
]
[[package]]
@@ -512,24 +488,13 @@ dependencies = [
"syn 2.0.48",
]
[[package]]
name = "darling_macro"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
dependencies = [
"darling_core 0.14.4",
"quote",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [
"darling_core 0.20.8",
"darling_core",
"quote",
"syn 2.0.48",
]
@@ -653,9 +618,6 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534"
dependencies = [
"byteorder",
"rand",
"rustc-hex",
"static_assertions",
]
@@ -694,7 +656,6 @@ dependencies = [
"cfg-if",
"parity-scale-codec",
"scale-info",
"serde",
]
[[package]]
@@ -1227,15 +1188,6 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "impl-codec"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f"
dependencies = [
"parity-scale-codec",
]
[[package]]
name = "impl-serde"
version = "0.4.0"
@@ -1794,9 +1746,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2"
dependencies = [
"fixed-hash",
"impl-codec",
"impl-serde",
"scale-info",
"uint",
]
@@ -1947,12 +1896,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc-hex"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
[[package]]
name = "rustc_version"
version = "0.4.0"
@@ -2102,25 +2045,11 @@ checksum = "afc79ba56a1c742f5aeeed1f1801f3edf51f7e818f0a54582cac6f131364ea7b"
dependencies = [
"derive_more",
"parity-scale-codec",
"primitive-types",
"scale-bits",
"scale-decode-derive",
"scale-type-resolver",
"smallvec",
]
[[package]]
name = "scale-decode-derive"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5398fdb3c7bea3cb419bac4983aadacae93fe1a7b5f693f4ebd98c3821aad7a5"
dependencies = [
"darling 0.14.4",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "scale-encode"
version = "0.6.0"
@@ -2129,26 +2058,11 @@ checksum = "628800925a33794fb5387781b883b5e14d130fece9af5a63613867b8de07c5c7"
dependencies = [
"derive_more",
"parity-scale-codec",
"primitive-types",
"scale-bits",
"scale-encode-derive",
"scale-type-resolver",
"smallvec",
]
[[package]]
name = "scale-encode-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a304e1af7cdfbe7a24e08b012721456cc8cecdedadc14b3d10513eada63233c"
dependencies = [
"darling 0.14.4",
"proc-macro-crate 1.3.1",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "scale-info"
version = "2.10.0"
@@ -2204,8 +2118,6 @@ version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c07ccfee963104335c971aaf8b7b0e749be8569116322df23f1f75c4ca9e4a28"
dependencies = [
"base58",
"blake2",
"derive_more",
"either",
"frame-metadata 15.1.0",
@@ -2215,8 +2127,6 @@ dependencies = [
"scale-encode",
"scale-info",
"scale-type-resolver",
"serde",
"yap",
]
[[package]]
@@ -2670,7 +2580,7 @@ dependencies = [
name = "subxt-macro"
version = "0.34.0"
dependencies = [
"darling 0.20.8",
"darling",
"parity-scale-codec",
"proc-macro-error",
"quote",
@@ -3316,12 +3226,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "yap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf"
[[package]]
name = "yew"
version = "0.20.0"
+1 -1
View File
@@ -58,7 +58,7 @@ web = [
[dependencies]
futures = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["raw_value"] }
serde_json = { workspace = true, features = ["default", "raw_value"] }
thiserror = { workspace = true }
tracing = { workspace = true }
+9 -6
View File
@@ -15,7 +15,8 @@ description = "Sign extrinsics to be submitted by Subxt"
keywords = ["parity", "subxt", "extrinsic", "signer"]
[features]
default = ["sr25519", "ecdsa", "subxt", "native"]
default = ["sr25519", "ecdsa", "subxt", "std", "native"]
std = ["regex/std", "sp-core-hashing/std", "pbkdf2/std", "sha2/std", "hmac/std", "bip39/std", "schnorrkel/std", "secp256k1/std", "sp-core/std"]
# Pick the signer implementation(s) you need by enabling the
# corresponding features. Note: I had more difficulties getting
@@ -34,26 +35,28 @@ web = ["getrandom/js", "subxt?/web"]
native = ["subxt?/native"]
[dependencies]
subxt = { workspace = true, optional = true, default-features = false }
regex = { workspace = true }
subxt = { workspace = true, optional = true }
regex = { workspace = true, features = ["unicode"] }
hex = { workspace = true }
cfg-if = { workspace = true }
codec = { package = "parity-scale-codec", workspace = true, features = ["derive"] }
sp-core-hashing = { workspace = true }
thiserror = { workspace = true }
derive_more = { workspace = true }
pbkdf2 = { workspace = true }
sha2 = { workspace = true }
hmac = { workspace = true }
zeroize = { workspace = true }
bip39 = { workspace = true }
schnorrkel = { workspace = true, optional = true }
secp256k1 = { workspace = true, features = ["recovery", "global-context"], optional = true }
secp256k1 = { workspace = true, optional = true, features = ["alloc", "recovery"] }
secrecy = { workspace = true }
# We only pull this in to enable the JS flag for schnorrkel to use.
getrandom = { workspace = true, optional = true }
[dev-dependencies]
sp-core = { workspace = true, features = ["std"] }
sp-core = { workspace = true }
sp-keyring = { workspace = true }
[package.metadata.cargo-machete]
+9 -4
View File
@@ -3,6 +3,8 @@
// see LICENSE for license details.
use super::DeriveJunction;
use alloc::vec::Vec;
use derive_more::Display;
use regex::Regex;
use secrecy::SecretString;
@@ -88,7 +90,7 @@ pub struct SecretUri {
pub junctions: Vec<DeriveJunction>,
}
impl std::str::FromStr for SecretUri {
impl core::str::FromStr for SecretUri {
type Err = SecretUriError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
@@ -115,14 +117,17 @@ impl std::str::FromStr for SecretUri {
}
/// This is returned if `FromStr` cannot parse a string into a `SecretUri`.
#[derive(Debug, Copy, Clone, PartialEq, thiserror::Error)]
#[derive(Debug, Copy, Clone, PartialEq, Display)]
pub enum SecretUriError {
/// Parsing the secret URI from a string failed; wrong format.
#[error("Invalid secret phrase format")]
#[display(fmt = "Invalid secret phrase format")]
InvalidFormat,
}
once_static! {
#[cfg(feature = "std")]
impl std::error::Error for SecretUriError {}
once_static_cloned! {
/// Interpret a phrase like:
///
/// ```text
+1
View File
@@ -2,6 +2,7 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use alloc::string::String;
use hmac::Hmac;
use pbkdf2::pbkdf2;
use sha2::Sha512;
+28 -16
View File
@@ -6,8 +6,10 @@
use codec::Encode;
use crate::crypto::{seed_from_entropy, DeriveJunction, SecretUri};
use core::str::FromStr;
use derive_more::{Display, From};
use hex::FromHex;
use secp256k1::{ecdsa::RecoverableSignature, Message, SecretKey, SECP256K1};
use secp256k1::{ecdsa::RecoverableSignature, Message, Secp256k1, SecretKey};
use secrecy::ExposeSecret;
const SEED_LENGTH: usize = 32;
@@ -68,7 +70,7 @@ impl Keypair {
let seed = Seed::from_hex(hex_str)?;
Self::from_seed(seed)?
} else {
let phrase = bip39::Mnemonic::parse(phrase.expose_secret().as_str())?;
let phrase = bip39::Mnemonic::from_str(phrase.expose_secret().as_str())?;
let pass_str = password.as_ref().map(|p| p.expose_secret().as_str());
Self::from_phrase(&phrase, pass_str)?
};
@@ -91,8 +93,9 @@ impl Keypair {
/// keypair.sign(b"Hello world!");
/// ```
pub fn from_phrase(mnemonic: &bip39::Mnemonic, password: Option<&str>) -> Result<Self, Error> {
let big_seed = seed_from_entropy(&mnemonic.to_entropy(), password.unwrap_or(""))
.ok_or(Error::InvalidSeed)?;
let (arr, len) = mnemonic.to_entropy_array();
let big_seed =
seed_from_entropy(&arr[0..len], password.unwrap_or("")).ok_or(Error::InvalidSeed)?;
let seed: Seed = big_seed[..SEED_LENGTH]
.try_into()
@@ -109,7 +112,8 @@ impl Keypair {
pub fn from_seed(seed: Seed) -> Result<Self, Error> {
let secret = SecretKey::from_slice(&seed).map_err(|_| Error::InvalidSeed)?;
Ok(Self(secp256k1::Keypair::from_secret_key(
SECP256K1, &secret,
&Secp256k1::signing_only(),
&secret,
)))
}
@@ -161,9 +165,9 @@ impl Keypair {
// From sp_core::ecdsa::sign_prehashed:
let wrapped = Message::from_digest_slice(&message_hash).expect("Message is 32 bytes; qed");
let recsig: RecoverableSignature =
SECP256K1.sign_ecdsa_recoverable(&wrapped, &self.0.secret_key());
Secp256k1::signing_only().sign_ecdsa_recoverable(&wrapped, &self.0.secret_key());
// From sp_core::ecdsa's `impl From<RecoverableSignature> for Signature`:
let (recid, sig) = recsig.serialize_compact();
let (recid, sig): (_, [u8; 64]) = recsig.serialize_compact();
let mut signature_bytes: [u8; 65] = [0; 65];
signature_bytes[..64].copy_from_slice(&sig);
signature_bytes[64] = (recid.to_i32() & 0xFF) as u8;
@@ -192,31 +196,39 @@ pub fn verify<M: AsRef<[u8]>>(sig: &Signature, message: M, pubkey: &PublicKey) -
};
let message_hash = sp_core_hashing::blake2_256(message.as_ref());
let wrapped = Message::from_digest_slice(&message_hash).expect("Message is 32 bytes; qed");
signature.verify(&wrapped, &public).is_ok()
Secp256k1::verification_only()
.verify_ecdsa(&wrapped, &signature, &public)
.is_ok()
}
/// An error handed back if creating a keypair fails.
#[derive(Debug, PartialEq, thiserror::Error)]
#[derive(Debug, PartialEq, Display, From)]
pub enum Error {
/// Invalid seed.
#[error("Invalid seed (was it the wrong length?)")]
#[display(fmt = "Invalid seed (was it the wrong length?)")]
#[from(ignore)]
InvalidSeed,
/// Invalid seed.
#[error("Invalid seed for ECDSA, contained soft junction")]
#[display(fmt = "Invalid seed for ECDSA, contained soft junction")]
#[from(ignore)]
SoftJunction,
/// Invalid phrase.
#[error("Cannot parse phrase: {0}")]
Phrase(#[from] bip39::Error),
#[display(fmt = "Cannot parse phrase: {_0}")]
Phrase(bip39::Error),
/// Invalid hex.
#[error("Cannot parse hex string: {0}")]
Hex(#[from] hex::FromHexError),
#[display(fmt = "Cannot parse hex string: {_0}")]
Hex(hex::FromHexError),
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
/// Dev accounts, helpful for testing but not to be used in production,
/// since the secret keys are known.
pub mod dev {
use super::*;
use std::str::FromStr;
use core::str::FromStr;
once_static_cloned! {
/// Equivalent to `{DEV_PHRASE}//Alice`.
+3 -6
View File
@@ -14,6 +14,9 @@
//! subxt transactions for chains supporting sr25519 signatures.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[macro_use]
mod utils;
@@ -40,9 +43,3 @@ pub use secrecy::{ExposeSecret, SecretString};
// SecretUri's can be parsed from strings and used to generate key pairs.
// DeriveJunctions are the "path" part of these SecretUris.
pub use crypto::{DeriveJunction, SecretUri, SecretUriError, DEV_PHRASE};
#[cfg(any(
all(feature = "web", feature = "native"),
not(any(feature = "web", feature = "native"))
))]
compile_error!("subxt-signer: exactly one of the 'web' and 'native' features should be used.");
+19 -10
View File
@@ -4,7 +4,11 @@
//! An sr25519 keypair implementation.
use core::str::FromStr;
use crate::crypto::{seed_from_entropy, DeriveJunction, SecretUri};
use derive_more::{Display, From};
use hex::FromHex;
use schnorrkel::{
derive::{ChainCode, Derivation},
@@ -72,7 +76,7 @@ impl Keypair {
let seed = Seed::from_hex(hex_str)?;
Self::from_seed(seed)?
} else {
let phrase = bip39::Mnemonic::parse(phrase.expose_secret().as_str())?;
let phrase = bip39::Mnemonic::from_str(phrase.expose_secret().as_str())?;
let pass_str = password.as_ref().map(|p| p.expose_secret().as_str());
Self::from_phrase(&phrase, pass_str)?
};
@@ -95,8 +99,9 @@ impl Keypair {
/// keypair.sign(b"Hello world!");
/// ```
pub fn from_phrase(mnemonic: &bip39::Mnemonic, password: Option<&str>) -> Result<Self, Error> {
let big_seed = seed_from_entropy(&mnemonic.to_entropy(), password.unwrap_or(""))
.ok_or(Error::InvalidSeed)?;
let (arr, len) = mnemonic.to_entropy_array();
let big_seed =
seed_from_entropy(&arr[0..len], password.unwrap_or("")).ok_or(Error::InvalidSeed)?;
let seed: Seed = big_seed[..SEED_LENGTH]
.try_into()
@@ -187,24 +192,28 @@ pub fn verify<M: AsRef<[u8]>>(sig: &Signature, message: M, pubkey: &PublicKey) -
}
/// An error handed back if creating a keypair fails.
#[derive(Debug, thiserror::Error)]
#[derive(Debug, Display, From)]
pub enum Error {
/// Invalid seed.
#[error("Invalid seed (was it the wrong length?)")]
#[display(fmt = "Invalid seed (was it the wrong length?)")]
#[from(ignore)]
InvalidSeed,
/// Invalid phrase.
#[error("Cannot parse phrase: {0}")]
Phrase(#[from] bip39::Error),
#[display(fmt = "Cannot parse phrase: {_0}")]
Phrase(bip39::Error),
/// Invalid hex.
#[error("Cannot parse hex string: {0}")]
Hex(#[from] hex::FromHexError),
#[display(fmt = "Cannot parse hex string: {_0}")]
Hex(hex::FromHexError),
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
/// Dev accounts, helpful for testing but not to be used in production,
/// since the secret keys are known.
pub mod dev {
use super::*;
use std::str::FromStr;
use core::str::FromStr;
once_static_cloned! {
/// Equivalent to `{DEV_PHRASE}//Alice`.
+11 -16
View File
@@ -7,34 +7,29 @@
/// Use like:
///
/// ```rust,ignore
/// once_static!{
/// once_static_cloned!{
/// /// Some documentation.
/// fn foo() -> Vec<u8> {
/// vec![1,2,3,4]
/// }
/// }
/// ```
macro_rules! once_static {
($($(#[$attr:meta])* $vis:vis fn $name:ident() -> $ty:ty { $expr:expr } )+) => {
$(
$(#[$attr])*
$vis fn $name() -> &'static $ty {
static VAR: std::sync::OnceLock<$ty> = std::sync::OnceLock::new();
VAR.get_or_init(|| { $expr })
}
)+
};
}
/// Like `once_static!` but clones the item out of static storage. Useful if it
///
/// Clones the item out of static storage. Useful if it
/// takes a while to create the item but cloning it is fairly cheap.
macro_rules! once_static_cloned {
($($(#[$attr:meta])* $vis:vis fn $name:ident() -> $ty:ty { $expr:expr } )+) => {
$(
$(#[$attr])*
$vis fn $name() -> $ty {
static VAR: std::sync::OnceLock<$ty> = std::sync::OnceLock::new();
VAR.get_or_init(|| { $expr }).clone()
cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
static VAR: std::sync::OnceLock<$ty> = std::sync::OnceLock::new();
VAR.get_or_init(|| { $expr }).clone()
} else {
{ $expr }
}
}
}
)+
};
+2 -3
View File
@@ -8,14 +8,13 @@ publish = false
wasm-bindgen-test = "0.3.24"
tracing-wasm = "0.2.1"
console_error_panic_hook = "0.1.7"
serde_json = "1"
# This crate is not a part of the workspace, because we want to
# enable the "web" feature here but don't want it enabled as part
# of workspace builds. Also disable the "subxt" feature here because
# we want to ensure it works in isolation of that.
subxt-signer = { path = "..", default-features = false, features = ["web", "sr25519", "ecdsa"] }
subxt-signer = { path = "..", default-features = false, features = ["web", "sr25519", "ecdsa", "std"] }
# this shouldn't be needed, it's in workspace.exclude, but still
# I get the complaint unless I add it...
[workspace]
[workspace]
+8 -8
View File
@@ -66,15 +66,15 @@ unstable-light-client = ["subxt-lightclient", "tokio-stream"]
[dependencies]
async-trait = { workspace = true }
codec = { package = "parity-scale-codec", workspace = true, features = ["derive"] }
scale-info = { workspace = true }
scale-value = { workspace = true }
scale-bits = { workspace = true }
scale-decode = { workspace = true }
scale-encode = { workspace = true }
scale-info = { workspace = true, features = ["default"] }
scale-value = { workspace = true, features = ["default"] }
scale-bits = { workspace = true, features = ["default"] }
scale-decode = { workspace = true, features = ["default"] }
scale-encode = { workspace = true, features = ["default"] }
futures = { workspace = true }
hex = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["raw_value"] }
serde_json = { workspace = true, features = ["default", "raw_value"] }
thiserror = { workspace = true }
tracing = { workspace = true }
frame-metadata = { workspace = true }
@@ -84,7 +84,7 @@ instant = { workspace = true }
# Provides some deserialization, types like U256/H256 and hashing impls like twox/blake256:
impl-serde = { workspace = true }
primitive-types = { workspace = true }
primitive-types = { workspace = true, features = ["codec", "scale-info", "serde"] }
sp-core-hashing = { workspace = true }
# For ss58 encoding AccountId32 to serialize them properly:
@@ -100,7 +100,7 @@ sp-runtime = { workspace = true, optional = true }
# Other subxt crates we depend on.
subxt-macro = { workspace = true }
subxt-metadata = { workspace = true }
subxt-metadata = { workspace = true, features = ["std"] }
subxt-lightclient = { workspace = true, optional = true, default-features = false }
# Light client support:
+204
View File
@@ -32,6 +32,21 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "bip39"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f"
dependencies = [
"bitcoin_hashes",
]
[[package]]
name = "bitcoin_hashes"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4"
[[package]]
name = "blake2b_simd"
version = "1.0.2"
@@ -101,6 +116,34 @@ dependencies = [
"typenum",
]
[[package]]
name = "curve25519-dalek"
version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"digest",
"fiat-crypto",
"platforms",
"rustc_version",
"subtle",
"zeroize",
]
[[package]]
name = "curve25519-dalek-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "derive_more"
version = "0.99.17"
@@ -122,6 +165,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
@@ -130,6 +174,12 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fiat-crypto"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
[[package]]
name = "frame-metadata"
version = "16.0.0"
@@ -151,6 +201,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "getrandom_or_panic"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9"
dependencies = [
"rand_core",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
@@ -161,6 +220,21 @@ dependencies = [
"allocator-api2",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "impl-trait-for-tuples"
version = "0.2.2"
@@ -209,6 +283,18 @@ version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "merlin"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d"
dependencies = [
"byteorder",
"keccak",
"rand_core",
"zeroize",
]
[[package]]
name = "once_cell"
version = "1.19.0"
@@ -239,6 +325,21 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest",
]
[[package]]
name = "platforms"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@@ -277,6 +378,37 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "regex"
version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc_version"
version = "0.4.0"
@@ -310,6 +442,32 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "schnorrkel"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0"
dependencies = [
"arrayref",
"arrayvec",
"curve25519-dalek",
"getrandom_or_panic",
"merlin",
"rand_core",
"sha2",
"subtle",
"zeroize",
]
[[package]]
name = "secrecy"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
dependencies = [
"zeroize",
]
[[package]]
name = "semver"
version = "1.0.21"
@@ -357,6 +515,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "subxt-core-no-std-tests"
version = "0.0.0"
@@ -364,6 +528,7 @@ dependencies = [
"libc_alloc",
"parity-scale-codec",
"subxt-metadata",
"subxt-signer",
]
[[package]]
@@ -378,6 +543,25 @@ dependencies = [
"sp-core-hashing",
]
[[package]]
name = "subxt-signer"
version = "0.34.0"
dependencies = [
"bip39",
"cfg-if",
"derive_more",
"hex",
"hmac",
"parity-scale-codec",
"pbkdf2",
"regex",
"schnorrkel",
"secrecy",
"sha2",
"sp-core-hashing",
"zeroize",
]
[[package]]
name = "syn"
version = "1.0.109"
@@ -485,3 +669,23 @@ dependencies = [
"quote",
"syn 2.0.48",
]
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
+1
View File
@@ -7,6 +7,7 @@ resolver = "2"
[dependencies]
subxt-metadata = { path = "../../metadata", default-features = false }
subxt-signer = { path = "../../signer", default-features = false, features = ["sr25519"] }
codec = { package = "parity-scale-codec", version = "3.6.9", default-features = false, features = ["derive"] }
libc_alloc = { version = "1.0.6" }
+17 -4
View File
@@ -34,14 +34,27 @@ extern crate alloc;
/// Including code here makes sure it is not pruned.
/// We want all code included to compile fine for the `thumbv7em-none-eabi` target.
fn compile_test() {
subxt_metadata_compiles();
}
fn subxt_metadata_compiles() {
// Subxt Metadata compiles:
use codec::Decode;
let bytes: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4];
subxt_metadata::Metadata::decode(&mut &bytes[..]).expect_err("invalid byte sequence");
const METADATA: &[u8] = include_bytes!("../../../artifacts/polkadot_metadata_small.scale");
subxt_metadata::Metadata::decode(&mut &METADATA[..]).expect("should be valid metadata");
// Subxt Signer compiles:
use subxt_signer::sr25519;
let keypair = sr25519::dev::alice();
let message = b"Hello!";
let _signature = keypair.sign(message);
let _public_key = keypair.public_key();
// Note: `ecdsa` is not compiling for the `thumbv7em-none-eabi` target.
//
// use subxt_signer::ecdsa;
// let keypair = ecdsa::dev::alice();
// let message = b"Hello!";
// let _signature = keypair.sign(message);
// let _public_key = keypair.public_key();
//
}