Skip to content

Commit

Permalink
Misc rustdoc updates (kaspanet#405)
Browse files Browse the repository at this point in the history
  • Loading branch information
aspect authored and D-Stacks committed Jan 23, 2024
1 parent f2b32b8 commit 947903e
Show file tree
Hide file tree
Showing 19 changed files with 86 additions and 694 deletions.
14 changes: 0 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,20 +175,6 @@ To build WASM on MacOS you need to install `llvm` from homebrew (at the time of

<details>

<summary>
React Native
</summary>

```bash
cd rusty-kaspa
cd wasm
./build-react-native
```

</details>

<details>

<summary>
ES6
</summary>
Expand Down
1 change: 1 addition & 0 deletions crypto/addresses/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ impl From<workflow_wasm::error::Error> for AddressError {
}
}

/// Address prefix identifying the network type this address belongs to (such as `kaspa`, `kaspatest`, `kaspasim`, `kaspadev`).
#[derive(
PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, BorshSchema,
)]
Expand Down
1 change: 1 addition & 0 deletions wallet/bip32/src/mnemonic/phrase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const PBKDF2_ROUNDS: u32 = 2048;
pub type Entropy32 = [u8; KEY_SIZE];
pub type Entropy16 = [u8; 16];

/// Word count for a BIP39 mnemonic phrase. Identifies mnemonic as 12 or 24 word variants.
#[derive(Default, Clone, Copy, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, BorshSchema)]
#[serde(rename_all = "kebab-case")]
pub enum WordCount {
Expand Down
14 changes: 11 additions & 3 deletions wallet/core/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ use kaspa_bip32::{ChildNumber, ExtendedPrivateKey, PrivateKey};
use kaspa_consensus_wasm::UtxoEntryReference;
use workflow_core::abortable::Abortable;

pub const DEFAULT_AMOUNT_PADDING: usize = 19;

/// Notification callback type used by [`Account::sweep`] and [`Account::send`].
/// Allows tracking in-flight transactions during transaction generation.
pub type GenerationNotifier = Arc<dyn Fn(&PendingTransaction) + Send + Sync>;
/// Scan notification callback type used by [`Account::derivation_scan`].
/// Provides derivation discovery scan progress information.
pub type ScanNotifier = Arc<dyn Fn(usize, usize, u64, Option<TransactionId>) + Send + Sync>;

/// General-purpose wrapper around [`AccountSettings`] (managed by [`Inner`]).
pub struct Context {
pub settings: AccountSettings,
}
Expand All @@ -43,6 +46,7 @@ impl Context {
}
}

/// Account `Inner` struct used by most account types.
pub struct Inner {
context: Mutex<Context>,
id: AccountId,
Expand Down Expand Up @@ -72,6 +76,8 @@ impl Inner {
}
}

/// Generic wallet [`Account`] trait implementation used
/// by different types of accounts.
#[async_trait]
pub trait Account: AnySync + Send + Sync + 'static {
fn inner(&self) -> &Arc<Inner>;
Expand Down Expand Up @@ -421,6 +427,7 @@ pub trait Account: AnySync + Send + Sync + 'static {

downcast_sync!(dyn Account);

/// Account trait used by legacy account types (BIP32 account types with the `'972` derivation path).
#[async_trait]
pub trait AsLegacyAccount: Account {
async fn create_private_context(
Expand All @@ -433,6 +440,7 @@ pub trait AsLegacyAccount: Account {
async fn clear_private_context(&self) -> Result<()>;
}

/// Account trait used by derivation capable account types (BIP32, MultiSig, etc.)
#[async_trait]
pub trait DerivationCapableAccount: Account {
fn derivation(&self) -> Arc<dyn AddressDerivationManagerTrait>;
Expand Down Expand Up @@ -611,7 +619,7 @@ pub trait DerivationCapableAccount: Account {

downcast_sync!(dyn DerivationCapableAccount);

pub fn create_private_keys<'l>(
pub(crate) fn create_private_keys<'l>(
account_kind: &AccountKind,
cosigner_index: u32,
account_index: u64,
Expand Down
10 changes: 10 additions & 0 deletions wallet/core/src/api/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,29 @@ use async_trait::async_trait;
use borsh::{BorshDeserialize, BorshSerialize};
use kaspa_wallet_macros::{build_wallet_client_transport_interface, build_wallet_server_transport_interface};

/// Transport interface supporting Borsh serialization
#[async_trait]
pub trait BorshTransport: Send + Sync {
async fn call(&self, op: u64, request: Vec<u8>) -> Result<Vec<u8>>;
}

/// Transport interface supporting Serde JSON serialization
#[async_trait]
pub trait SerdeTransport: Send + Sync {
async fn call(&self, op: &str, request: &str) -> Result<String>;
}

/// Transport interface enum supporting either Borsh and Serde JSON serialization
#[derive(Clone)]
pub enum Transport {
Borsh(Arc<dyn BorshTransport>),
Serde(Arc<dyn SerdeTransport>),
}

/// [`WalletServer`] is a server-side transport interface that declares
/// API methods that can be invoked via Borsh or Serde messages containing
/// serializations created using the [`Transport`] interface. The [`WalletServer`]
/// is a counter-part to [`WalletClient`].
pub struct WalletServer {
pub wallet_api: Arc<dyn WalletApi>,
}
Expand Down Expand Up @@ -90,6 +97,9 @@ impl WalletServer {
]}
}

/// [`WalletClient`] is a client-side transport interface declaring
/// API methods that can be invoked via WalletApi method calls.
/// [`WalletClient`] is a counter-part to [`WalletServer`].
pub struct WalletClient {
pub transport: Transport,
}
Expand Down
2 changes: 2 additions & 0 deletions wallet/core/src/derivation/gen0/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Derivation management for legacy account derivation scheme `972`
mod hd;
pub use hd::{PubkeyDerivationManagerV0, WalletDerivationManagerV0};
pub mod import;
1 change: 1 addition & 0 deletions wallet/core/src/derivation/gen1/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// Derivation management for the Kaspa standard derivation scheme `111111'`
mod hd;
pub use hd::{PubkeyDerivationManager, WalletDerivationManager};
pub mod import;
8 changes: 8 additions & 0 deletions wallet/core/src/deterministic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use kaspa_hashes::Hash;
use kaspa_utils::as_slice::AsSlice;
use secp256k1::PublicKey;

/// Deterministic byte sequence derived from account data (can be used for auxiliary data storage encryption).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
pub struct AccountStorageKey(pub(crate) Hash);

Expand All @@ -32,6 +33,7 @@ impl std::fmt::Display for AccountStorageKey {
}
}

/// Deterministic Account Id derived from account data.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
pub struct AccountId(pub(crate) Hash);

Expand Down Expand Up @@ -86,6 +88,7 @@ where
hashes
}

/// Create deterministic hashes from BIP32 account data.
pub fn from_bip32<const N: usize>(prv_key_data_id: &PrvKeyDataId, data: &bip32::Payload) -> [Hash; N] {
let hashable = DeterministicHashData {
account_kind: &bip32::BIP32_ACCOUNT_KIND.into(),
Expand All @@ -98,6 +101,7 @@ pub fn from_bip32<const N: usize>(prv_key_data_id: &PrvKeyDataId, data: &bip32::
make_hashes(hashable)
}

/// Create deterministic hashes from legacy account data.
pub fn from_legacy<const N: usize>(prv_key_data_id: &PrvKeyDataId, _data: &legacy::Payload) -> [Hash; N] {
let hashable = DeterministicHashData {
account_kind: &legacy::LEGACY_ACCOUNT_KIND.into(),
Expand All @@ -110,6 +114,7 @@ pub fn from_legacy<const N: usize>(prv_key_data_id: &PrvKeyDataId, _data: &legac
make_hashes(hashable)
}

/// Create deterministic hashes from multisig account data.
pub fn from_multisig<const N: usize>(prv_key_data_ids: &Option<Arc<Vec<PrvKeyDataId>>>, data: &multisig::Payload) -> [Hash; N] {
let hashable = DeterministicHashData {
account_kind: &multisig::MULTISIG_ACCOUNT_KIND.into(),
Expand All @@ -122,6 +127,7 @@ pub fn from_multisig<const N: usize>(prv_key_data_ids: &Option<Arc<Vec<PrvKeyDat
make_hashes(hashable)
}

/// Create deterministic hashes from keypair account data.
pub(crate) fn from_keypair<const N: usize>(prv_key_data_id: &PrvKeyDataId, data: &keypair::Payload) -> [Hash; N] {
let hashable = DeterministicHashData {
account_kind: &keypair::KEYPAIR_ACCOUNT_KIND.into(),
Expand All @@ -134,6 +140,7 @@ pub(crate) fn from_keypair<const N: usize>(prv_key_data_id: &PrvKeyDataId, data:
make_hashes(hashable)
}

/// Create deterministic hashes from a public key.
pub fn from_public_key<const N: usize>(account_kind: &AccountKind, public_key: &PublicKey) -> [Hash; N] {
let hashable: DeterministicHashData<[PrvKeyDataId; 0]> = DeterministicHashData {
account_kind,
Expand All @@ -146,6 +153,7 @@ pub fn from_public_key<const N: usize>(account_kind: &AccountKind, public_key: &
make_hashes(hashable)
}

/// Create deterministic hashes from arbitrary data (supplied data slice must be deterministic).
pub fn from_data<const N: usize>(account_kind: &AccountKind, data: &[u8]) -> [Hash; N] {
let hashable: DeterministicHashData<[PrvKeyDataId; 0]> = DeterministicHashData {
account_kind,
Expand Down
15 changes: 15 additions & 0 deletions wallet/core/src/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ use sha2::{Digest, Sha256};
use std::ops::{Deref, DerefMut};
use zeroize::Zeroize;

/// Encryption algorithms supported by the Wallet framework.
#[derive(Clone, Copy, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
pub enum EncryptionKind {
XChaCha20Poly1305,
}

/// Abstract data container that can contain either plain or encrypted data and
/// transform the data between the two states.
#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
#[serde(tag = "encryptable", content = "payload")]
pub enum Encryptable<T> {
Expand Down Expand Up @@ -92,6 +95,7 @@ impl<T> From<T> for Encryptable<T> {
}
}

/// Abstract decrypted data container.
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
pub struct Decrypted<T>(pub(crate) T)
where
Expand Down Expand Up @@ -155,6 +159,7 @@ where
}
}

/// Encrypted data container (wraps an encrypted payload)
#[derive(Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
pub struct Encrypted {
encryption_kind: EncryptionKind,
Expand Down Expand Up @@ -199,53 +204,61 @@ impl Encrypted {
}
}

/// WASM32 binding for `SHA256` hash function.
#[wasm_bindgen(js_name = "sha256")]
pub fn js_sha256_hash(data: JsValue) -> Result<String> {
let data = data.try_as_vec_u8()?;
let hash = sha256_hash(&data);
Ok(hash.as_ref().to_hex())
}

/// WASM32 binding for `SHA256d` hash function.
#[wasm_bindgen(js_name = "sha256d")]
pub fn js_sha256d_hash(data: JsValue) -> Result<String> {
let data = data.try_as_vec_u8()?;
let hash = sha256d_hash(&data);
Ok(hash.as_ref().to_hex())
}

/// WASM32 binding for `argon2sha256iv` hash function.
#[wasm_bindgen(js_name = "argon2sha256iv")]
pub fn js_argon2_sha256iv_phash(data: JsValue, byte_length: usize) -> Result<String> {
let data = data.try_as_vec_u8()?;
let hash = argon2_sha256iv_hash(&data, byte_length)?;
Ok(hash.as_ref().to_hex())
}

/// Produces `SHA256` hash of the given data.
pub fn sha256_hash(data: &[u8]) -> Secret {
let mut sha256 = Sha256::default();
sha256.update(data);
Secret::new(sha256.finalize().to_vec())
}

/// Produces `SHA256d` hash of the given data.
pub fn sha256d_hash(data: &[u8]) -> Secret {
let mut sha256 = Sha256::default();
sha256.update(data);
sha256_hash(sha256.finalize().as_slice())
}

/// Produces `argon2sha256iv` hash of the given data.
pub fn argon2_sha256iv_hash(data: &[u8], byte_length: usize) -> Result<Secret> {
let salt = sha256_hash(data);
let mut key = vec![0u8; byte_length];
Argon2::default().hash_password_into(data, salt.as_ref(), &mut key)?;
Ok(key.into())
}

/// WASM32 binding for `encryptXChaCha20Poly1305` function.
#[wasm_bindgen(js_name = "encryptXChaCha20Poly1305")]
pub fn js_encrypt_xchacha20poly1305(text: String, password: String) -> Result<String> {
let secret = sha256_hash(password.as_bytes());
let encrypted = encrypt_xchacha20poly1305(text.as_bytes(), &secret)?;
Ok(general_purpose::STANDARD.encode(encrypted))
}

/// Encrypts the given data using `XChaCha20Poly1305` algorithm.
pub fn encrypt_xchacha20poly1305(data: &[u8], secret: &Secret) -> Result<Vec<u8>> {
let private_key_bytes = argon2_sha256iv_hash(secret.as_ref(), 32)?;
let key = Key::from_slice(private_key_bytes.as_ref());
Expand All @@ -258,6 +271,7 @@ pub fn encrypt_xchacha20poly1305(data: &[u8], secret: &Secret) -> Result<Vec<u8>
Ok(buffer)
}

/// WASM32 binding for `decryptXChaCha20Poly1305` function.
#[wasm_bindgen(js_name = "decryptXChaCha20Poly1305")]
pub fn js_decrypt_xchacha20poly1305(text: String, password: String) -> Result<String> {
let secret = sha256_hash(password.as_bytes());
Expand All @@ -266,6 +280,7 @@ pub fn js_decrypt_xchacha20poly1305(text: String, password: String) -> Result<St
Ok(String::from_utf8(encrypted.as_ref().to_vec())?)
}

/// Decrypts the given data using `XChaCha20Poly1305` algorithm.
pub fn decrypt_xchacha20poly1305(data: &[u8], secret: &Secret) -> Result<Secret> {
let private_key_bytes = argon2_sha256iv_hash(secret.as_ref(), 32)?;
let key = Key::from_slice(private_key_bytes.as_ref());
Expand Down
1 change: 1 addition & 0 deletions wallet/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use workflow_rpc::client::error::Error as RpcError;
use workflow_wasm::jserror::*;
use workflow_wasm::printable::*;

/// [`Error`](enum@Error) variants emitted by the wallet framework.
#[derive(Debug, Error)]
pub enum Error {
#[error("{0}")]
Expand Down
2 changes: 2 additions & 0 deletions wallet/core/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ pub enum Events {
/// contain a developer-assigned internal id.
id: UtxoContextId,
},
/// A general wallet framework error, emitted when an unexpected
/// error occurs within the wallet framework.
Error {
message: String,
},
Expand Down
17 changes: 17 additions & 0 deletions wallet/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@
//! within native Rust applications as well as within the NodeJS
//! and browser environments via WASM32.
//!
//! For JavaScript / TypeScript environments, there are two
//! available NPM modules:
//! - <https://www.npmjs.com/package/kaspa>
//! - <https://www.npmjs.com/package/kaspa-wasm>
//!
//! The `kaspa-wasm` module is a pure WASM32 module that includes
//! the entire wallet framework, but does not support RPC, while
//! the `kaspa` module also includes `isomorphic-ws` simulating
//! the W3C WebSocket available natively in browsers and supports RPC.
//!
//! JavaScript examples for using this framework can be found at:
//! <https://github.com/kaspanet/rusty-kaspa/tree/master/wasm/nodejs>
//!
//! For pre-built browser-compatible WASM32 redistributables of this
//! framework please see the releases section of the Rusty Kaspa
//! repository at <https://github.com/kaspanet/rusty-kaspa/releases>.
//!
extern crate alloc;
extern crate self as kaspa_wallet_core;
Expand Down
8 changes: 6 additions & 2 deletions wallet/core/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ impl AsRef<[u8]> for PersonalMessage<'_> {
}
}

/// Sign a message with the given private key
pub fn sign_message(msg: &PersonalMessage, privkey: &[u8; 32]) -> Result<Vec<u8>, Error> {
let hash = calc_personal_message_hash(msg);

Expand All @@ -24,8 +25,11 @@ pub fn sign_message(msg: &PersonalMessage, privkey: &[u8; 32]) -> Result<Vec<u8>
Ok(sig.to_vec())
}

/// Ok(()) if the signature matches the given message and pubkey
/// Error if any of the inputs are incorrect, or the signature is invalid
/// Verifies signed message.
///
/// Produces `Ok(())` if the signature matches the given message and [`secp256k1::Error`]
/// if any of the inputs are incorrect, or the signature is invalid.
///
pub fn verify_message(msg: &PersonalMessage, signature: &Vec<u8>, pubkey: &XOnlyPublicKey) -> Result<(), Error> {
let hash = calc_personal_message_hash(msg);
let msg = secp256k1::Message::from_slice(hash.as_bytes().as_slice())?;
Expand Down
1 change: 1 addition & 0 deletions wallet/core/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
//! [`Result`] type alias bound to the framework [`Error`](crate::error::Error) enum.
//!
/// [`Result`] type alias bound to the framework [`Error`](crate::error::Error) enum.
pub type Result<T, E = super::error::Error> = std::result::Result<T, E>;
1 change: 1 addition & 0 deletions wallet/core/src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;

/// Secret container for sensitive data. Performs memory zeroization on drop.
#[derive(Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize, BorshSchema)]
pub struct Secret(Vec<u8>);

Expand Down
Loading

0 comments on commit 947903e

Please sign in to comment.