-
Notifications
You must be signed in to change notification settings - Fork 57
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
KVAC Mint and Wallet #619
base: main
Are you sure you want to change the base?
KVAC Mint and Wallet #619
Conversation
crates/cashu/Cargo.toml
Outdated
swagger = ["dep:utoipa"] | ||
mint = ["dep:uuid"] | ||
wallet = [] | ||
bench = [] | ||
kvac = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To include the KVAC dependency cashu_kvac
only when the kvac
feature is enabled, you'd have to do two things:
First, specify the kvac
feature should pull in the dependency:
kvac = [] | |
kvac = [dep:cashu_kvac] |
Second, add an optional = true
to the cashu_kvac
dependency below, similar for example to utoipa
. This will mean the dependency should not be included, unless an activated feature explicitly needs it.
/// Kvac Coin | ||
/// | ||
/// A KVAC coin as intended to be saved in the wallet. | ||
#[cfg(feature = "wallet")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it will be easier to maintain if the mint-specific structs and traits would be placed in a mint.rs
submodule (for example crates/cashu/src/nuts/kvac/mint.rs
) and the wallet-specific stuff in wallet.rs
right next to it. Then you wouldn't need to specify #[cfg(feature = "wallet")]
for each struct, but you could directly apply the feature flag to the submodule import, like for example here:
cdk/crates/cdk-redb/src/lib.rs
Lines 9 to 12 in a82e3eb
#[cfg(feature = "mint")] | |
pub mod mint; | |
#[cfg(feature = "wallet")] | |
pub mod wallet; |
crates/cashu/src/nuts/kvac.rs
Outdated
let hex_of_hash = hex::encode(hash.to_byte_array()); | ||
Id { | ||
version: KeySetVersion::Version00, | ||
id: hex::decode(&hex_of_hash[0..14]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's hex::encode
then hex::decode
a few lines below. Wouldn't it be simpler to directly use the original hash.to_byte_array()
?
data.extend(kvac_keys.0.I.to_bytes()); | ||
let hash = Sha256::hash(&data); | ||
let hex_of_hash = hex::encode(hash.to_byte_array()); | ||
Id { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of constructing the Id
by specifying the inner fields from the kvac.rs
caller, I would suggest to instead:
- add an
Id::new_v0_from_hash(h: Hash)
innut02.rs
, which would internally take the first 7 bytes and construct a v0Id
- keep the inner fields of
Id
private
kvac.rs
could then call Id::new_v0_from_hash(..)
, which would make it simpler and more readable.
Another benefit is that other future callers could make use of new_v0_from_hash
too.
active BOOL NOT NULL, | ||
input_fee_ppk INTEGER NOT NULL, | ||
counter INTEGER NOT NULL DEFAULT 0, | ||
FOREIGN KEY(mint_url) REFERENCES mint(mint_url) ON UPDATE CASCADE ON DELETE CASCADE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to treat the mint_url
as foreign key, linking the kvac_keyset
and mint
tables and propagating a mint
row deletion here as well.
I haven't thought it through, but at first sight this is tricky and probably incorrect because:
- the same mint (and therefore each of its keysets) can have multiple
mint_url
s - deleting a
mint_url
(for example of a mint with multiple URLs) doesn't necessarily mean the caller wants to delete the keyset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just basically copied the SQL for the other "normal" keysets because they are pretty much the same
Description
This PR adds basic support for KVAC (amountless ecash). Uses cashu-kvac to verify/create ZKPs and algebraic MACs. The protocol explanation with all the definitions is given here.
TL;DR
Amount
Amounts are encoded into Pedersen Commitments (
amount * G + blinding_factor * H
).Request Inputs and Outputs
Every request has inputs and outputs. To get initial inputs wallets do
bootstrap
requests to get a bunch of coins of 0 value for free.Outputs length to each mint/melt/swap request are fixed to 2, while inputs length might be >= 2. This is done in order to enhance privacy AND reduce the workload (Range Proofs are beefy).
MACs
MAC
is equivalent to theBlindSignature
. It's the authentication stamp generated by the Mint.r
, but there is also a blinding factor for the script commitment)Script Attributes
What the hell are "Nullifiers"?
Normal ecash uses the
Y = HashToG(secret)
to identify a coin. That is called a nullifier.In here we use the Randomized Amount Commitment (
Ca
), which is just the amount commitment after it's beenrandomized. In the code it's often called just "nullifier" or "nullifiers"
Endpoints
Endpoints for checking and requesting mint/melt quotes are in common with normal ecash.
Other endpoints are:
v2/kvac
:swap
: swap requestmint
: mint requestmelt
: melt requestbootstrap
: bootstrap requestcheckstate
: checking the state of some nullifiersrestore
: restore coins from their tags (if generated deterministically)Run The Example
Run with
cargo run --example kvac-wallet
[TBC...]