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 all 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
12 changes: 7 additions & 5 deletions libwallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ 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, default-features = false }
mnemonic = { package = "bip0039", version = "0.10.1", default-features = false, optional = true}
sp-core = { version = "32.0.0", optional = true }
rand_core = {version = "0.6.3", optional = true}
# substrate related
schnorrkel = {version = "0.11.4", default-features = false, optional = true}# soft derivation in no_std
rand_chacha = {version = "0.3.1", default-features = false, optional = true}

hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
log = "0.4.17"
# vault os
keyring = {version = "1.1.2", optional = true}
# vault pass
Expand All @@ -35,7 +36,7 @@ serde_json = {version = "1.0", default-features = false, features = ["alloc"]}
dirs = "4.0"

[features]
# default = ["std", "substrate", "vault_simple", "mnemonic", "rand", "vault_pass", "vault_os", "util_pin"]
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 +47,7 @@ util_pin = ["pbkdf2", "hmac", "sha2"]
vault_os = ["keyring"]
vault_pass = ["prs-lib"]
vault_simple = []
vault_pjs = ["pjs", "sp-core"]

[workspace]
members = [
Expand Down
38 changes: 15 additions & 23 deletions libwallet/js/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use serde_wasm_bindgen::from_value;
use wasm_bindgen::prelude::*;

use libwallet::{vault::Simple, Signer, Wallet};
use libwallet::{vault::Simple, Account, Signer, Wallet};

#[derive(Serialize, Deserialize)]
pub enum WalletConstructor {
Expand All @@ -13,7 +13,7 @@ pub enum WalletConstructor {
#[wasm_bindgen(inspectable)]
pub struct JsWallet {
phrase: String,
wallet: Wallet<Simple>,
wallet: Wallet<Simple<String>>,
}

#[wasm_bindgen]
Expand Down Expand Up @@ -48,74 +48,66 @@ impl JsWallet {

#[wasm_bindgen]
pub async fn unlock(&mut self, credentials: JsValue) -> Result<(), JsValue> {
let credentials: <Simple as libwallet::Vault>::Credentials =
let credentials: <Simple<String> as libwallet::Vault>::Credentials =
if credentials.is_null() || credentials.is_undefined() {
None
} else {
from_value(credentials).unwrap_or(None)
};

self.wallet
.unlock(credentials)
.unlock(None, credentials)
.await
.map_err(|e| JsError::new(&e.to_string()))?;

Ok(())
}

#[wasm_bindgen(js_name = getAddress)]
pub fn get_address(&self) -> Result<JsPublicAddress, JsError> {
pub fn get_address(&self) -> Result<JsBytes, JsError> {
if self.wallet.is_locked() {
return Err(JsError::new(
"The wallet is locked. You should unlock it first by using the .unlock() method",
));
}

Ok(JsPublicAddress::new(
self.wallet.default_account().public().as_ref().to_vec(),
Ok(JsBytes::new(
self.wallet.default_account().unwrap().public().as_ref().to_vec(),
))
}

#[wasm_bindgen]
pub fn sign(&self, message: &[u8]) -> Result<Box<[u8]>, JsError> {
pub async fn sign(&self, message: &[u8]) -> Result<JsBytes, JsError> {
if self.wallet.is_locked() {
return Err(JsError::new(
"The wallet is locked. You should unlock it first by using the .unlock() method",
));
}

let sig = self.wallet.sign(message);

if !self
.wallet
.default_account()
.verify(&message, &sig.as_ref())
{
return Err(JsError::new("Message could not be verified"));
}

Ok(sig.as_ref().to_vec().into_boxed_slice())
let sig = self.wallet.sign(message).await.map_err(|_| JsError::new("Error while signing"))?;
let f = sig.as_ref().to_vec();
Ok(JsBytes::new(f))
}

#[wasm_bindgen]
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<bool, JsError> {
pub async fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<bool, JsError> {
if self.wallet.is_locked() {
return Err(JsError::new(
"The wallet is locked. You should unlock it first by using the .unlock() method",
));
}

Ok(self.wallet.default_account().verify(msg, sig))
Ok(self.wallet.default_account().unwrap().verify(msg, sig).await)
}
}

#[wasm_bindgen(inspectable)]
pub struct JsPublicAddress {
pub struct JsBytes {
repr: Vec<u8>,
}

#[wasm_bindgen]
impl JsPublicAddress {
impl JsBytes {
#[wasm_bindgen(constructor)]
pub fn new(repr: Vec<u8>) -> Self {
Self { repr }
Expand Down
8 changes: 6 additions & 2 deletions libwallet/src/key_pair.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::{convert::TryFrom, fmt::Debug};
use core::{convert::{TryFrom, TryInto}, fmt::Debug};

pub use derive::Derive;

Expand All @@ -20,7 +20,11 @@ pub trait Pair: Signer + Derive {
pub trait Public: AsRef<[u8]> + Debug {}
impl<const N: usize> Public for Bytes<N> {}

pub trait Signature: AsRef<[u8]> + Debug + PartialEq {}
pub trait Signature: AsRef<[u8]> + Debug + PartialEq {
fn as_bytes<const N: usize>(&self) -> Bytes<N> {
self.as_ref().try_into().expect("error getting the bytes")
}
}
impl<const N: usize> Signature for Bytes<N> {}

/// Something that can sign messages
Expand Down
13 changes: 9 additions & 4 deletions libwallet/src/vault.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
//! Collection of supported Vault backends
#[cfg(feature = "vault_os")]
mod os;

#[cfg(feature = "vault_pjs")]
pub mod pjs;

#[cfg(feature = "vault_pjs")]
pub use pjs::*;

#[cfg(feature = "vault_pass")]
mod pass;
mod simple;

#[cfg(feature = "vault_os")]
pub use os::*;
#[cfg(feature = "vault_pass")]
pub use pass::*;
pub use simple::*;

mod simple;
pub use simple::*;
use crate::account::Account;

/// Abstraction for storage of private keys that are protected by some credentials.
Expand Down
87 changes: 87 additions & 0 deletions libwallet/src/vault/pjs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
extern crate alloc;
use crate::{any::AnySignature, Account, Signer, Vault};
use alloc::vec::Vec;
use pjs::{Account as PjsAccount, Error, PjsExtension};
use log;
use hex;
use sp_core::crypto::{AccountId32, Ss58Codec};

#[derive(Clone)]
pub struct Pjs {
inner: PjsExtension,
}

impl Pjs {
pub async fn connect(name: &str) -> Result<Self, Error> {
Ok(Pjs {
inner: PjsExtension::connect(name).await?,
})
}

pub async fn list_accounts(&mut self) -> Result<Vec<PjsAccount>, Error> {
self.inner.fetch_accounts().await?;
Ok(self.inner.accounts())
}

pub fn select_account(&mut self, idx: u8) {
self.inner.select_account(idx)
}
}

impl Signer for Pjs {
type Signature = AnySignature;

async fn sign_msg(&self, msg: impl AsRef<[u8]>) -> Result<Self::Signature, ()> {
log::info!("signing: {}", hex::encode(&msg.as_ref()));
let sig = self.inner.sign(msg.as_ref()).await.map_err(|_| ())?;
log::info!("signature {:?}", hex::encode(&sig));
Ok(AnySignature::from(sig))
}

async fn verify(&self, _: impl AsRef<[u8]>, _: impl AsRef<[u8]>) -> bool {
unimplemented!()
}
}

impl Account for Pjs {
fn public(&self) -> impl crate::Public {
let mut key = [0u8; 32];

let address = self
.inner
.get_selected()
.expect("an account must be defined")
.address();

let address = <AccountId32 as Ss58Codec>::from_string(&address)
.expect("it must be a valid ss58 address");
key.copy_from_slice(address.as_ref());
key
}
}

impl core::fmt::Display for Pjs {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
for byte in self.public().as_ref() {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}

impl Vault for Pjs {
type Id = u8;
type Credentials = ();
type Account = Pjs;
type Error = Error;

async fn unlock(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we .connect on unlock?

&mut self,
account: Self::Id,
_: impl Into<Self::Credentials>,
) -> Result<Self::Account, Self::Error> {
let mut pjs_signer = self.clone();
pjs_signer.select_account(account);
Ok(pjs_signer)
}
}
8 changes: 4 additions & 4 deletions pjs-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ version = "0.1.0"
edition = "2021"

[dependencies]
wasm-bindgen = { version = "0.2.92", default-features = false }
wasm-bindgen = { version = "0.2.91", default-features = false }
wasm-bindgen-futures = "0.4.42"
log = "0.4.19"
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }

[dependencies.web-sys]
version = "0.3.69"
Expand All @@ -18,6 +20,4 @@ default = ["js"]
js = []

[lib]
crate-type = ["cdylib"]


crate-type = ["cdylib", "lib"]
Loading
Loading