Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pjs vault #48

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
07cf095
feat: Vault exporting signer instead of root account
S0c5 Apr 24, 2024
ad5cb5c
feat: Add AccountSigner struct for managing public/private key pairs …
S0c5 Apr 24, 2024
60e6635
refactor: Update type definition in account_generation.rs and key_pai…
S0c5 Apr 25, 2024
f946cd5
fix: fix type Id for vault os
S0c5 Apr 25, 2024
4c590fb
feat: pjs vault
S0c5 Apr 26, 2024
dcf11d6
chore: update cargo.toml
S0c5 Apr 26, 2024
a771f4b
Merge branch 'main' into feat/libwallet-with-vault-exportin-signer
S0c5 Apr 26, 2024
d7264e2
feat(account): Add methods to handle default accounts and update meth…
S0c5 Apr 26, 2024
45566f1
merge
S0c5 Apr 26, 2024
f86167c
add pjs vault
S0c5 Apr 26, 2024
9e205ea
refactor: Refactor code structure and improve async functions in Pjs …
S0c5 Apr 28, 2024
273efa0
down grade version
manuelcastrobarinas Apr 28, 2024
6a93643
refactor: Update dependencies and code structure in libwallet and pjs…
S0c5 Apr 30, 2024
f749db8
feat(key_pair): add method as_bytes to Signature trait
S0c5 Apr 30, 2024
0932335
style: Update key_pair.rs with improved error message for try_into co…
S0c5 Apr 30, 2024
8350abe
refactor: Rename variable from `pub_key` to `address` in Pjs impl Acc…
S0c5 Apr 30, 2024
00770b4
style: Fix default-features typo in pjs dependency definition in Carg…
S0c5 Apr 30, 2024
019ae8e
style: Update default-features value for pjs dependency in Cargo.toml
S0c5 Apr 30, 2024
acc0c22
style: Update attribute syntax for conditional wasm_bindgen feature u…
S0c5 Apr 30, 2024
a719e4c
feat: Add logging to PjsExtension for debugging purposes
S0c5 Apr 30, 2024
2938928
feat: Add logging statement to display data before signing
S0c5 Apr 30, 2024
887ca83
feat: Add logging for signature in PjsExtension
S0c5 Apr 30, 2024
e5d8409
fix: Fix accessing the correct variable in get! macro to retrieve the…
S0c5 Apr 30, 2024
d693e48
feat(libwallet, pjs-rs): Add logging of signatures in the code using …
S0c5 Apr 30, 2024
5b91696
style: Improve code readability by refactoring signature extraction l…
S0c5 Apr 30, 2024
af56efa
feat: Add logging for final signature in PjsExtension
S0c5 Apr 30, 2024
ae8e20e
fix: Add logging for s and b values in PjsExtension
S0c5 Apr 30, 2024
d0fd3d1
fix: Update default value for b to 1
S0c5 Apr 30, 2024
fb3f59c
fix: Fix parsing issue in PjsExtension impl and add logging informati…
S0c5 Apr 30, 2024
6728810
refactor: Remove commented-out code and unnecessary closure in PjsExt…
S0c5 Apr 30, 2024
3256b6a
fix: Fix syntax error in from_hex function in PjsExtension
S0c5 Apr 30, 2024
a55bc3b
feat: Log message data before signing and after getting the signature
S0c5 May 1, 2024
85201dd
fix: Use hex::encode instead of custom to_hex implementation in sign …
S0c5 May 1, 2024
8aaf83b
fix: Update sign method to prepend '0x' to the encoded payload before…
S0c5 May 1, 2024
2dd7810
fix: Update the type field value to "payload" and remove the prefix "…
S0c5 May 1, 2024
049b4ef
fix: Update the type field value to "bytes" instead of "payload" in P…
S0c5 May 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions libwallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ serde = {version = "1.0", default-features = false, features = ["derive"], optio
hmac = {version = "0.12.1", default-features = false, optional = true}
pbkdf2 = {version = "0.11.0", default-features = false, optional = true}
sha2 = {version = "0.10.2", default-features = false, optional = true}

mnemonic = {package = "bip0039", version = "0.10.1", default-features = false, optional = true}
pjs = { path = "../pjs-rs", optional = true }
mnemonic = { package = "bip0039", version = "0.10.1", default-features = false, optional = true}

rand_core = {version = "0.6.3", optional = true}
# substrate related
Expand All @@ -35,8 +35,7 @@ serde_json = {version = "1.0", default-features = false, features = ["alloc"]}
dirs = "4.0"

[features]
# The library has no default features but this can be uncommented during development
# default = [ "std", "substrate", "vault_simple", "vault_os", "vault_pass", "mnemonic", "util_pin", "rand", ]
default = ["std", "substrate", "vault_simple", "mnemonic", "rand", "vault_pass", "vault_os", "util_pin", "vault_pjs"]
rand = ["rand_core", "schnorrkel?/getrandom"]
sr25519 = ["dep:schnorrkel"]
std = [
Expand All @@ -46,6 +45,8 @@ substrate = ["sr25519"]
util_pin = ["pbkdf2", "hmac", "sha2"]
vault_os = ["keyring"]
vault_pass = ["prs-lib"]
vault_simple = []
vault_pjs = ["pjs"]

[workspace]
members = [
Expand Down
8 changes: 4 additions & 4 deletions libwallet/examples/account_generation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use libwallet::{self, vault};
use libwallet::{self, vault, Account};
use std::env;

type Wallet = libwallet::Wallet<vault::Simple>;
type Wallet = libwallet::Wallet<vault::Simple<String>>;

#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -15,10 +15,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
};

let mut wallet = Wallet::new(vault);
wallet.unlock(None).await?;
wallet.unlock(None, None).await?;
let account = wallet.default_account();

println!("Secret phrase: \"{phrase}\"");
println!("Default Account: 0x{account}");
println!("Default Account: 0x{:?}", account.unwrap());
Ok(())
}
11 changes: 7 additions & 4 deletions libwallet/examples/persisted_in_keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use libwallet::{self, vault, Language};

use std::{env, error::Error};

type Wallet = libwallet::Wallet<vault::OSKeyring>;
type Wallet = libwallet::Wallet<vault::OSKeyring<String>>;

const TEST_USER: &str = "test_user";

Expand All @@ -11,12 +11,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
let pin = env::args().nth(1);
let pin = pin.as_ref().map(String::as_str);

let vault = vault::OSKeyring::new(TEST_USER, Language::default());
let vault = vault::OSKeyring::<String>::new(TEST_USER, Language::default());

let mut wallet = Wallet::new(vault);
wallet.unlock(pin).await?;


wallet.unlock(None, pin).await?;

let account = wallet.default_account();
println!("Default account: {}", account);
println!("Default account: {}", account.unwrap());

Ok(())
}
7 changes: 4 additions & 3 deletions libwallet/examples/persisted_in_pass.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use dirs::home_dir;
use libwallet::{self, vault::Pass, Language};
use std::error::Error;
type Wallet = libwallet::Wallet<Pass>;
type PassVault = Pass<String>;
type Wallet = libwallet::Wallet<PassVault>;

#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -13,10 +14,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
let vault = Pass::new(store_path.to_str().unwrap(), Language::default());
let mut wallet = Wallet::new(vault);

wallet.unlock(account).await?;
wallet.unlock(None, account).await?;

let account = wallet.default_account();
println!("Default account: {}", account);
println!("Default account: {}", account.unwrap());

Ok(())
}
104 changes: 5 additions & 99 deletions libwallet/src/account.rs
Original file line number Diff line number Diff line change
@@ -1,103 +1,9 @@
use core::fmt::{Debug, Display};

use crate::{
any::{self, AnySignature},
Derive, Network, Pair, Public, RootAccount,
Public, Signer,
};
use arrayvec::ArrayString;
// use regex::Regex;
// use sp_core::crypto::DeriveJunction;

const MAX_PATH_LEN: usize = 16;

/// Account is an abstration around public/private key pairs that are more convenient to use and
/// can hold extra metadata. Accounts are constructed by the wallet and are used to sign messages.
#[derive(Debug)]
pub struct Account {
pair: Option<any::Pair>,
network: Network,
path: ArrayString<MAX_PATH_LEN>,
name: ArrayString<{ MAX_PATH_LEN - 2 }>,
}

impl Account {
pub(crate) fn new<'a>(name: impl Into<Option<&'a str>>) -> Self {
let n = name.into().unwrap_or_else(|| "default");
let mut path = ArrayString::from("//").unwrap();
path.push_str(&n);
Account {
pair: None,
network: Network::default(),
name: ArrayString::from(&n).expect("short name"),
path,
}
}

pub fn switch_network(self, net: impl Into<Network>) -> Self {
Account {
network: net.into(),
..self
}
}

pub fn name(&self) -> &str {
&self.name
}

pub fn public(&self) -> impl Public {
self.pair.as_ref().expect("account unlocked").public()
}

pub fn network(&self) -> &Network {
&self.network
}

pub fn is_locked(&self) -> bool {
self.pair.is_none()
}

pub(crate) fn unlock(&mut self, root: &RootAccount) -> &Self {
if self.is_locked() {
self.pair = Some(root.derive(&self.path));
}
self
}
}

impl crate::Signer for Account {
type Signature = AnySignature;

fn sign_msg<M: AsRef<[u8]>>(&self, msg: M) -> Self::Signature {
self.pair.as_ref().expect("account unlocked").sign_msg(msg)
}

fn verify<M: AsRef<[u8]>>(&self, msg: M, sig: &[u8]) -> bool {
self.pair
.as_ref()
.expect("account unlocked")
.verify(msg, sig)
}
}

#[cfg(feature = "serde")]
impl serde::Serialize for Account {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;

let mut state = serializer.serialize_struct("Account", 1)?;
state.serialize_field("network", &self.network)?;
state.serialize_field("path", self.path.as_str())?;
state.serialize_field("name", self.name.as_str())?;
state.end()
}
}

impl core::fmt::Display for Account {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
for byte in self.public().as_ref() {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
pub trait Account: Signer + Display {
fn public(&self) -> impl Public;
}
31 changes: 17 additions & 14 deletions libwallet/src/key_pair.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use core::fmt::Debug;
use core::{convert::TryFrom, fmt::Debug};

pub use derive::Derive;

use self::any::AnySignature;

type Bytes<const N: usize> = [u8; N];

/// A key pair with a public key
Expand All @@ -24,12 +26,13 @@ impl<const N: usize> Signature for Bytes<N> {}
/// Something that can sign messages
pub trait Signer {
type Signature: Signature;
fn sign_msg<M: AsRef<[u8]>>(&self, msg: M) -> Self::Signature;
fn verify<M: AsRef<[u8]>>(&self, msg: M, sig: &[u8]) -> bool;
async fn sign_msg(&self, data: impl AsRef<[u8]>) -> Result<Self::Signature, ()>;
async fn verify(&self, msg: impl AsRef<[u8]>, sig: impl AsRef<[u8]>) -> bool;
}

/// Wrappers to represent any supported key pair.
pub mod any {
use crate::Signer;

use super::{Public, Signature};
use core::fmt;

Expand Down Expand Up @@ -91,19 +94,17 @@ pub mod any {
impl super::Signer for Pair {
type Signature = AnySignature;

fn sign_msg<M: AsRef<[u8]>>(&self, msg: M) -> Self::Signature {
async fn sign_msg(&self, msg: impl AsRef<[u8]>) -> Result<Self::Signature, ()> {
match self {
#[cfg(feature = "sr25519")]
Pair::Sr25519(p) => p.sign_msg(msg).into(),
Pair::Sr25519(p) => Ok(p.sign_msg(msg).await?.into()),
}
}

fn verify<M: AsRef<[u8]>>(&self, msg: M, sig: &[u8]) -> bool {
async fn verify(&self, msg: impl AsRef<[u8]>, sig: impl AsRef<[u8]>) -> bool {
match self {
#[cfg(feature = "sr25519")]
Pair::Sr25519(p) => super::Signer::verify(p, msg, sig),
#[cfg(not(feature = "sr25519"))]
Pair::_None => unreachable!(),
Pair::Sr25519(p) => super::Signer::verify(p, msg, sig).await,
}
}
}
Expand Down Expand Up @@ -145,6 +146,7 @@ pub mod any {
#[cfg(not(feature = "sr25519"))]
_None,
}

impl AsRef<[u8]> for AnySignature {
fn as_ref(&self) -> &[u8] {
match self {
Expand Down Expand Up @@ -198,13 +200,13 @@ pub mod sr25519 {
impl Signer for Pair {
type Signature = Signature;

fn sign_msg<M: AsRef<[u8]>>(&self, msg: M) -> Self::Signature {
async fn sign_msg(&self, msg: impl AsRef<[u8]>) -> Result<Self::Signature, ()> {
let context = signing_context(SIGNING_CTX);
self.sign(context.bytes(msg.as_ref())).to_bytes()
Ok(self.sign(context.bytes(msg.as_ref())).to_bytes())
}

fn verify<M: AsRef<[u8]>>(&self, msg: M, sig: &[u8]) -> bool {
let sig = match schnorrkel::Signature::from_bytes(sig) {
async fn verify(&self, msg: impl AsRef<[u8]>, sig: impl AsRef<[u8]>) -> bool {
let sig = match schnorrkel::Signature::from_bytes(sig.as_ref()) {
Ok(s) => s,
Err(_) => return false,
};
Expand Down Expand Up @@ -310,6 +312,7 @@ pub mod sr25519 {
] {
let phrase = Mnemonic::from_phrase(phrase).unwrap();
let seed = Pin::from("").protect::<64>(&phrase.entropy());

let root: super::Pair = Pair::from_bytes(&seed);
let derived = root.derive(path);
assert_eq!(&derived.public(), pubkey);
Expand Down
Loading
Loading