Skip to content
TOwInOKPublic

About

Client library for WhatsMiner ASIC mining hardware

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

matroskin

matroskin logo

Asynchronous Rust client library for WhatsMiner ASIC mining hardware.

Crates.io Docs.rs CI API v3.0.3 License MSRV 1.85+


matroskin is an asynchronous Rust client for WhatsMiner ASIC hardware. An internal actor state machine encapsulates the WhatsMiner v3 TCP protocol—handling framing, encrypted authentication, and automatic reconnects behind a lock-free, strongly-typed actor.send(cmd) interface.

Warning

Operational & API Version Status:

  • API Version: The library implements WhatsMiner API v3.0.3. The upstream API has since released v3.0.5; features introduced in 3.0.4/3.0.5 are not yet supported.
  • Hardware Validation: Read-only queries (get.*) and verified control commands (set.miner.fastboot, set.system.reboot, set.user.permission) have been tested on physical hardware (marked ●). All other state-modifying operations (marked ○) are verified against the mock harness and must be evaluated with caution prior to production use.

Highlights

  • Actor-based FSM: Single-owner Tokio task manages the connection lifecycle without mutexes or runtime locks.
  • Complete API Coverage: All 39 WhatsMiner v3 commands implemented as typed, owned structures.
  • Simple Command Dispatch: Uniform actor.send(cmd).await? interface with strongly-typed request and response payloads.
  • Resilient Reconnection: Transparent backoff and reconnect queuing that preserves pending commands during connection drops.
  • Secure by Default: Zeroizing credentials and session salts on drop, AES-256-ECB parameter encryption, and automatic secret redaction in debug logs.

Quickstart

Add matroskin and tokio to your Cargo.toml (requires Rust 1.85+ / Edition 2024):

[dependencies]
matroskin = "0.1.0"
tokio = { version = "1", features = ["full"] }

Basic Usage

Note: Initializing an Actor via Actor::new requires an active Tokio runtime context. Actor::clone() creates an independent actor instance; wrap in Arc<Actor> to share one connected actor across tasks.

use matroskin::{
    account::Account,
    actor::Actor,
    command::get_device_info::GetDeviceInfo,
    password::Password,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Initialize actor in `Created` state (synchronous in memory, no network I/O yet).
    let actor = Actor::new("10.10.10.10:4433", Account::Super, Password::Super);

    // 2. Queue non-blocking connect intent.
    actor.connect()?;

    // 3. Send an owned command by value.
    // The command mailbox waits until the actor establishes a Connected session.
    let response = actor.send(GetDeviceInfo::all()).await?;
    println!("Device info: {:#?}", response.msg);

    // 4. Graceful non-blocking shutdown intent.
    actor.shutdown()?;
    Ok(())
}

Flat Commands & Typed Parameters

All commands use flat structures with named fields and .new(...) constructors. Executing actor.send(cmd) returns Response<C::Response>, where C::Response is the typed payload in .msg:

use matroskin::{
    account::{Account, Users},
    actor::Actor,
    command::{
        get_device_info::GetDeviceInfo,
        set_miner_pools::{PoolConfig, SetMinerPools},
        set_user_permission::SetUserPermission,
    },
    password::Password,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let actor = Actor::new("10.10.10.10:4433", Account::Super, Password::Super);
    actor.connect()?;

    // Query device info: response payload is DeviceInfo (optional salt is redacted)
    let info = actor.send(GetDeviceInfo::all()).await?;
    println!("Salt present: {}", info.msg.salt.is_some());

    // Set user permissions: requires All permission level
    let perm = SetUserPermission::new(Users::User1, "set.system.led,set.miner.pools");
    actor.send(perm).await?;

    // Configure pools: 3 fixed entries with protected credentials (AES-256-ECB encrypted)
    let pools = [
        PoolConfig::new("stratum+tcp://pool1.com:3333", "worker1", "pass1"),
        PoolConfig::new("stratum+tcp://pool2.com:3333", "worker2", "pass2"),
        PoolConfig::new("stratum+tcp://pool3.com:3333", "worker3", "pass3"),
    ];
    actor.send(SetMinerPools::new(pools)).await?;

    actor.shutdown()?;
    Ok(())
}

Direct Streaming Operations

Streaming operations take exclusive ownership of the network transport while active:

use matroskin::{account::Account, actor::Actor, password::Password};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let actor = Actor::new("10.10.10.10:4433", Account::Super, Password::Super);
    actor.connect()?;

    // Download system logs directly into an owned AsyncWrite destination
    let log_file = tokio::fs::File::create("miner.log").await?;
    actor.download_log(log_file).await?;

    // Firmware upload accepts an owned AsyncRead source and exact byte length
    // (Use with caution on production devices)
    // let fw_file = tokio::fs::File::open("firmware.bin").await?;
    // let len = fw_file.metadata().await?.len();
    // actor.upload_firmware(fw_file, len).await?;

    actor.shutdown()?;
    Ok(())
}

Command Inventory

Status of implemented commands against the WhatsMiner API v3 (target specification: v3.0.3, current upstream: v3.0.5):

  • ● Hardware verified: Tested and confirmed on physical WhatsMiner hardware.
  • ○ Mock verified: Verified against the in-process mock test suite; use on physical hardware at your own risk.
Command Status Level Access Description
get.device.custom_data ● Public Read-only Retrieve device custom metadata fields
get.device.info ● Public Read-only Retrieve system, network, miner, power, and error status
get.fan.setting ● Public Read-only Get fan speed and temperature offset summary
get.log.download ● Public Read-only Stream packaged .tgz log archive (download_log)
get.miner.history ● Public Read-only Get miner history within a time window (≤ 24h)
get.miner.setting ● Public Read-only Get power mode, limit, and fastboot settings
get.miner.status ● Public Read-only Get detailed status: summary, pools, and edevs
get.system.setting ● Public Read-only Get system settings (hostname, NTP, timezone)
set.device.custom_data ○ Secured Read-Write Set custom metadata key-value pair
set.fan.poweroff_cool ○ Secured Read-Write Toggle power-off cooling
set.fan.temp_offset ○ Secured Read-Write Set fan temperature target offset (-10..10°C)
set.fan.zero_speed ○ Secured Read-Write Toggle zero fan speed mode
set.log.upload ○ Secured Read-Write Configure remote syslog upload server
set.miner.cointype ○ Secured Read-Write Set coin mining algorithm (e.g. BTC)
set.miner.fast_hash ○ Secured Read-Write Toggle fast hash mode
set.miner.fastboot ● Secured Read-Write Toggle fastboot mode
set.miner.heat_mode ○ Secured Read-Write Configure heat mode (e.g. normal, heating)
set.miner.pools ○ Encrypted Read-Write Set 3 stratum mining pools (AES-256-ECB)
set.miner.power ○ Secured Read-Write Set target power consumption in Watts
set.miner.power_limit ○ Secured Read-Write Set maximum power limit threshold in Watts
set.miner.power_mode ○ Secured Read-Write Set power mode (low, normal, high)
set.miner.power_percent ○ Secured Read-Write Set target power percentage and mode
set.miner.report ○ Secured Read-Write Configure periodic status report interval
set.miner.restore_setting ○ Secured Read-Write Restore miner settings to factory defaults
set.miner.service ○ Secured Read-Write Restart or stop miner hashing service
set.miner.target_freq ○ Secured Read-Write Adjust target frequency percentage
set.miner.upfreq_speed ○ Secured Read-Write Configure frequency ramp-up speed
set.system.factory_reset ○ Secured All (Super) Factory reset control board settings
set.system.hostname ○ Secured Read-Write Set device network hostname
set.system.led ○ Secured Read-Write Set LED status mode (auto, manual, off)
set.system.net_config ○ Secured All (Super) Configure network interface (DHCP or static)
set.system.ntp_server ○ Secured Read-Write Configure NTP time synchronization servers
set.system.reboot ● Secured Read-Write Immediately restart the ASIC controller
set.system.time_randomized ○ Encrypted Read-Write Configure randomized start/stop time jitter
set.system.timezone ○ Encrypted Read-Write Configure system timezone name and offset
set.system.update_firmware ○ Secured All (Super) Stream binary firmware update (upload_firmware)
set.system.webpools ○ Secured Read-Write Toggle web pool modification lock
set.user.change_passwd ○ Encrypted Super/User Change account password (AES-256-ECB)
set.user.permission ● Secured All (Super) Set comma-separated allowed commands for user

Development & Testing

The repository provides built-in Cargo aliases in .cargo/config.toml:

# Run all unit tests, mock device tests, and doc tests
cargo test

# Run in-process mock device tests (thread-isolated)
cargo test-mock

# Strict linter check across all targets and features
cargo lint

# Check code formatting
cargo fmt-check

# Verify documentation builds without warnings
cargo doc-check

# List hardware integration tests without connecting to an ASIC
cargo test-real-list

# Run physical hardware tests (requires ASIC reachable at MINER_ADDR)
MINER_ADDR=10.20.1.2:4433 cargo test --test real_device --features real-device

License

Dual-licensed under either of:

at your option.

About

Client library for WhatsMiner ASIC mining hardware

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages