Skip to content

Commit

Permalink
🚧 init cli uzing zig-cli lib
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelStark committed Aug 9, 2024
1 parent 89d14a4 commit b0bde50
Show file tree
Hide file tree
Showing 15 changed files with 6,273 additions and 6,388 deletions.
77 changes: 52 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,68 @@

# About

Coconut 🥥 is a Cashu protocol implementation in Zig.
Coconut 🥥 is a Cashu Wallet and Mint implementation in Zig.

For now it contains only the Blind Diffie-Hellmann Key Exchange (BDHKE) implementation.
## CLI Usage

## Usage
The Coconut wallet provides a command-line interface for various operations. Here's how to use it:

### Running
### General Help

```bash
zig build run
To see the general help and available commands, run:

```text
$ coconut --help
Version: 0.1.0
Author: Coconut Contributors
USAGE:
coconut [OPTIONS]
COMMANDS:
info Display information about the Coconut wallet
OPTIONS:
-h, --help Show this help output.
--color <VALUE> When to use colors (*auto*, never, always).
```

Example output:
### Info Command

The `info` command displays information about the Coconut wallet. Here's its specific help:

```text
Starting BDHKE test
Secret message: test_message
Alice's private key (a): 0000000000000000000000000000000000000000000000000000000000000001
Alice's public key (A): 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
r private key: 0000000000000000000000000000000000000000000000000000000000000001
Blinding factor (r): 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
Blinded message (B_): 025cc16fe33b953e2ace39653efb3e7a7049711ae1d8a2f7a9108753f1cdea742b
Step 1 complete: Message blinded
Blinded signature (C_): 025cc16fe33b953e2ace39653efb3e7a7049711ae1d8a2f7a9108753f1cdea742b
DLEQ proof - e: e87bf88896743cd89e8f8316811553a15d74538f205c9cff1f72ff23e624cc1f
DLEQ proof - s: 9f546cb383df3d8c0d36c925045287c113df293c3429083d2c5728cfdbddd925
Step 2 complete: Blinded message signed
Alice's DLEQ verification successful
Unblinded signature (C): 0215fdc277c704590f3c3bcc08cf9a8f748f46619b96268cece86442b6c3ac461b
Step 3 complete: Signature unblinded
Carol's DLEQ verification successful
Final verification successful
BDHKE test completed successfully
$ coconut info --help
USAGE:
coconut info [OPTIONS]
OPTIONS:
-m, --mint Fetch mint information
-n, --mnemonic Show your mnemonic
-h, --help Show this help output.
```

### Example Usage

Here's an example of using the `info` command with the `--mnemonic` option:

```text
$ coconut info --mnemonic
Version: 0.1.0
Wallet: coconut
Cashu dir: /Users/abdel/Library/Application Support/coconut
Mints:
- URL: https://example.com:3338
- Keysets:
- ID: example_id unit: sat active: True fee (ppk): 0
Mnemonic:
- example word1 word2 word3 ...
Nostr:
- Public key: npub1example...
- Relays: wss://example1.com, wss://example2.com
```

This command displays general information about the wallet, including the version, wallet name, Cashu directory, mint information, and Nostr details. The `--mnemonic` option additionally displays the wallet's mnemonic phrase.

Note: Be cautious when using the `--mnemonic` option, as it displays sensitive information. Make sure you're in a secure environment when viewing your mnemonic.

## Benchmarks

This project includes performance benchmarks for each step of the BDHKE process, as well as the end-to-end flow.
Expand Down
63 changes: 62 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
const std = @import("std");
const build_helpers = @import("build_helpers.zig");
const package_name = "coconut";
const package_path = "src/lib.zig";

// List of external dependencies that this package requires.
const external_dependencies = [_]build_helpers.Dependency{
.{
.name = "zig-cli",
.module_name = "zig-cli",
},
};

fn buildSecp256k1(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step.Compile {
const lib = b.addStaticLibrary(.{ .name = "zig-libsecp256k1", .target = target, .optimize = optimize });
Expand All @@ -25,29 +36,79 @@ fn buildSecp256k1(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std
}

pub fn build(b: *std.Build) !void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});

// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});

// **************************************************************
// * HANDLE DEPENDENCY MODULES *
// **************************************************************
const dependencies_opts = .{
.target = target,
.optimize = optimize,
};

// This array can be passed to add the dependencies to lib, executable, tests, etc using `addModule` function.
const deps = build_helpers.generateModuleDependencies(
b,
&external_dependencies,
dependencies_opts,
) catch unreachable;

// **************************************************************
// * COCONUT AS A MODULE *
// **************************************************************
// expose coconut as a module
_ = b.addModule(package_name, .{
.root_source_file = b.path(package_path),
.imports = deps,
});

// libsecp256k1 static C library.
const libsecp256k1 = try buildSecp256k1(b, target, optimize);
b.installArtifact(libsecp256k1);

// **************************************************************
// * COCONUT AS A LIBRARY *
// **************************************************************
const lib = b.addStaticLibrary(.{
.name = "coconut",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});

// Add dependency modules to the library.
for (deps) |mod| lib.root_module.addImport(
mod.name,
mod.module,
);
// This declares intent for the library to be installed into the standard
// location when the user invokes the "install" step (the default step when
// running `zig build`).
b.installArtifact(lib);

// **************************************************************
// * COCONUT AS AN EXECUTABLE *
// **************************************************************
const exe = b.addExecutable(.{
.name = "coconut",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.linkLibrary(libsecp256k1);
// Add dependency modules to the executable.
for (deps) |mod| exe.root_module.addImport(
mod.name,
mod.module,
);

b.installArtifact(exe);

Expand Down
9 changes: 6 additions & 3 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@
.url = "https://github.com/karlseguin/zul/archive/ae0c27350c0db6b460f22cba30b6b0c4a02d1ffd.zip",
.hash = "1220457e2c8867f6734520d9b335f01e1d851d6fe7adaa7f6f0756158acaf6c5e87f",
},
.@"zig-cli" = .{
.url = "https://github.com/sam701/zig-cli/archive/9a94c4803a52e54c26b198096d63fb5bde752da2.zip",
.hash = "1220ab73fb7cc11b2308edc3364988e05efcddbcac31b707f55e6216d1b9c0da13f1",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
// For example...
//"LICENSE",
//"README.md",
"LICENSE",
"README.md",
},
}
65 changes: 65 additions & 0 deletions build_helpers.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const std = @import("std");

/// Represents a dependency on an external package.
pub const Dependency = struct {
name: []const u8,
module_name: []const u8,
};

/// Generate an array of Build.Module.Import from the external dependencies.
/// # Arguments
/// * `b` - The build object.
/// * `external_dependencies` - The external dependencies.
/// * `dependencies_opts` - The options to use when generating the dependency modules.
/// # Returns
/// A new array of Build.Module.Import.
pub fn generateModuleDependencies(
b: *std.Build,
external_dependencies: []const Dependency,
dependencies_opts: anytype,
) ![]std.Build.Module.Import {
var dependency_modules = std.ArrayList(*std.Build.Module).init(b.allocator);
defer _ = dependency_modules.deinit();

// Populate dependency modules.
for (external_dependencies) |dep| {
const module = b.dependency(
dep.name,
dependencies_opts,
).module(dep.module_name);
_ = dependency_modules.append(module) catch unreachable;
}
return try toModuleDependencyArray(
b.allocator,
dependency_modules.items,
external_dependencies,
);
}

/// Convert an array of Build.Module pointers to an array of Build.Module.Import.
/// # Arguments
/// * `allocator` - The allocator to use for the new array.
/// * `modules` - The array of Build.Module pointers to convert.
/// * `ext_deps` - The array of external dependencies.
/// # Returns
/// A new array of Build.Module.Import.
fn toModuleDependencyArray(
allocator: std.mem.Allocator,
modules: []const *std.Build.Module,
ext_deps: []const Dependency,
) ![]std.Build.Module.Import {
var deps = std.ArrayList(std.Build.Module.Import).init(allocator);
defer deps.deinit();

for (
modules,
0..,
) |module_ptr, i| {
try deps.append(.{
.name = ext_deps[i].name,
.module = module_ptr,
});
}

return deps.toOwnedSlice();
}
Loading

0 comments on commit b0bde50

Please sign in to comment.