Crash fixes, reorg handling, and sync performance improvements
Some checks failed
Rust / Build on macOS-latest (push) Has been cancelled
Rust / Build on ubuntu-16.04 (push) Has been cancelled
Rust / Build on windows-latest (push) Has been cancelled
Rust / Linux ARMv7 (push) Has been cancelled
Rust / Linux ARM64 (push) Has been cancelled
Rust / Build on ubuntu-latest (push) Has been cancelled
Some checks failed
Rust / Build on macOS-latest (push) Has been cancelled
Rust / Build on ubuntu-16.04 (push) Has been cancelled
Rust / Build on windows-latest (push) Has been cancelled
Rust / Linux ARMv7 (push) Has been cancelled
Rust / Linux ARM64 (push) Has been cancelled
Rust / Build on ubuntu-latest (push) Has been cancelled
- Fix FFI panics with catch_unwind and safe CString construction - Handle poisoned mutex/RwLock after prior panics instead of crashing - Fix empty block list panics in clear_blocks and invalidate_block - Reuse Tokio runtime across block fetch batches to reduce overhead - Add fetch_blocks_with_runtime for caller-managed runtime lifecycle - Update branding, dependencies, and checkpoints for DragonX
This commit is contained in:
176
.github/workflows/rust.yml
vendored
176
.github/workflows/rust.yml
vendored
@@ -1,88 +1,88 @@
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-16.04, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli.exe
|
||||
path: target/release/silentdragonlite-cli.exe
|
||||
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-silentdragonlite-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/silentdragonlite-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-silentdragonlite-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/silentdragonlite-cli
|
||||
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-16.04, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli.exe
|
||||
path: target/release/silentdragonlite-cli.exe
|
||||
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-silentdragonlite-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/silentdragonlite-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-silentdragonlite-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/silentdragonlite-cli
|
||||
|
||||
|
||||
208
.github/workflows/rust_BACKUP_5752.yml
vendored
208
.github/workflows/rust_BACKUP_5752.yml
vendored
@@ -1,104 +1,104 @@
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
=======
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
=======
|
||||
name: ${{ matrix.os }}-zecwallet-cli
|
||||
path: target/release/zecwallet-cli
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
<<<<<<< HEAD
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli.exe
|
||||
path: target/release/silentdragonlite-cli.exe
|
||||
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
=======
|
||||
name: ${{ matrix.os }}-zecwallet-cli.exe
|
||||
path: target/release/zecwallet-cli.exe
|
||||
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-silentdragonlite-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/silentdragonlite-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-silentdragonlite-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/silentdragonlite-cli
|
||||
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
=======
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
=======
|
||||
name: ${{ matrix.os }}-zecwallet-cli
|
||||
path: target/release/zecwallet-cli
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
<<<<<<< HEAD
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli.exe
|
||||
path: target/release/silentdragonlite-cli.exe
|
||||
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
=======
|
||||
name: ${{ matrix.os }}-zecwallet-cli.exe
|
||||
path: target/release/zecwallet-cli.exe
|
||||
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-silentdragonlite-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/silentdragonlite-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-silentdragonlite-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/silentdragonlite-cli
|
||||
|
||||
|
||||
160
.github/workflows/rust_BASE_5752.yml
vendored
160
.github/workflows/rust_BASE_5752.yml
vendored
@@ -1,80 +1,80 @@
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{ matrix.os }}-zecwallet-cli
|
||||
path: target/release/zecwallet-cli
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-zecwallet-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/zecwallet-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-zecwallet-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/zecwallet-cli
|
||||
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{ matrix.os }}-zecwallet-cli
|
||||
path: target/release/zecwallet-cli
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-zecwallet-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/zecwallet-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-zecwallet-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/zecwallet-cli
|
||||
|
||||
|
||||
186
.github/workflows/rust_LOCAL_5752.yml
vendored
186
.github/workflows/rust_LOCAL_5752.yml
vendored
@@ -1,93 +1,93 @@
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
<<<<<<< HEAD
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
=======
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli.exe
|
||||
path: target/release/silentdragonlite-cli.exe
|
||||
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-silentdragonlite-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/silentdragonlite-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-silentdragonlite-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/silentdragonlite-cli
|
||||
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
<<<<<<< HEAD
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
=======
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli
|
||||
path: target/release/silentdragonlite-cli
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
name: ${{ matrix.os }}-silentdragonlite-cli.exe
|
||||
path: target/release/silentdragonlite-cli.exe
|
||||
|
||||
>>>>>>> 959755d705b18d13a8dbdf0502c47818fe7a4e94
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-silentdragonlite-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/silentdragonlite-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-silentdragonlite-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/silentdragonlite-cli
|
||||
|
||||
|
||||
176
.github/workflows/rust_REMOTE_5752.yml
vendored
176
.github/workflows/rust_REMOTE_5752.yml
vendored
@@ -1,88 +1,88 @@
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
name: ${{ matrix.os }}-zecwallet-cli
|
||||
path: target/release/zecwallet-cli
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
name: ${{ matrix.os }}-zecwallet-cli.exe
|
||||
path: target/release/zecwallet-cli.exe
|
||||
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-zecwallet-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/zecwallet-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-zecwallet-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/zecwallet-cli
|
||||
|
||||
name: Rust
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.38.0
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release --all
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --release --all
|
||||
- name: Upload ubuntu/macos
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
|
||||
with:
|
||||
name: ${{ matrix.os }}-zecwallet-cli
|
||||
path: target/release/zecwallet-cli
|
||||
- name: Upload windows
|
||||
uses: actions/upload-artifact@v1
|
||||
if: contains(matrix.os, 'windows')
|
||||
with:
|
||||
name: ${{ matrix.os }}-zecwallet-cli.exe
|
||||
path: target/release/zecwallet-cli.exe
|
||||
|
||||
|
||||
linux_arm7:
|
||||
name: Linux ARMv7
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target armv7-unknown-linux-gnueabihf
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_armv7-zecwallet-cli
|
||||
path: target/armv7-unknown-linux-gnueabihf/release/zecwallet-cli
|
||||
|
||||
linux_aarch64:
|
||||
name: Linux ARM64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --release --target aarch64-unknown-linux-gnu
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: linux_aarch64-zecwallet-cli
|
||||
path: target/aarch64-unknown-linux-gnu/release/zecwallet-cli
|
||||
|
||||
|
||||
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,7 +1,7 @@
|
||||
target/
|
||||
.vscode/
|
||||
history.txt
|
||||
/.idea/
|
||||
tarpaulin-report.html
|
||||
/log*
|
||||
silentdragonlite-cli
|
||||
target/
|
||||
.vscode/
|
||||
history.txt
|
||||
/.idea/
|
||||
tarpaulin-report.html
|
||||
/log*
|
||||
silentdragonlite-cli
|
||||
|
||||
5766
Cargo.lock
generated
5766
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
14
Cargo.toml
@@ -1,8 +1,8 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"lib",
|
||||
"cli",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
[workspace]
|
||||
members = [
|
||||
"lib",
|
||||
"cli",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
debug = false
|
||||
46
Makefile
46
Makefile
@@ -1,23 +1,23 @@
|
||||
.PHONY: format help
|
||||
# Help system from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
||||
.DEFAULT_GOAL := help
|
||||
# Copyright (c) 2019-2024 Jahway603 & The Hush Developers
|
||||
# Released under the GPLv3
|
||||
#
|
||||
# DragonX Silentdragonlite-cli Makefile
|
||||
PROJECT_NAME := "silentdragonxlite-cli"
|
||||
|
||||
help:
|
||||
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
about: ## Display release info
|
||||
printf "DragonX Silentdragonlite-cli Makefile by jahway603\n"
|
||||
|
||||
build: ## Build the release
|
||||
./util/build.sh
|
||||
cp `pwd`/target/release/$(PROJECT_NAME) .
|
||||
printf "DragonX silentdragonxlite-cli is ready for you\n"
|
||||
|
||||
clean: ## Clean the repo
|
||||
cargo clean
|
||||
rm $(PROJECT_NAME)
|
||||
.PHONY: format help
|
||||
# Help system from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
||||
.DEFAULT_GOAL := help
|
||||
# Copyright (c) 2019-2024 Jahway603 & The Hush Developers
|
||||
# Released under the GPLv3
|
||||
#
|
||||
# DragonX Silentdragonlite-cli Makefile
|
||||
PROJECT_NAME := "silentdragonxlite-cli"
|
||||
|
||||
help:
|
||||
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
about: ## Display release info
|
||||
printf "DragonX Silentdragonlite-cli Makefile by jahway603\n"
|
||||
|
||||
build: ## Build the release
|
||||
./util/build.sh
|
||||
cp `pwd`/target/release/$(PROJECT_NAME) .
|
||||
printf "DragonX silentdragonxlite-cli is ready for you\n"
|
||||
|
||||
clean: ## Clean the repo
|
||||
cargo clean
|
||||
rm $(PROJECT_NAME)
|
||||
|
||||
200
README.md
200
README.md
@@ -1,100 +1,100 @@
|
||||
# SilentDragonXLite CLI
|
||||
|
||||
`silentdragonxlite-cli` is a command line SilentDragonXLite light client. To use it, download the latest binary from the releases page and run `./silentdragonxlite-cli` or compile it yourself as documented below.
|
||||
|
||||
This will launch the interactive prompt. Type `help` to get a list of commands
|
||||
|
||||
## Running in non-interactive mode:
|
||||
You can also run `silentdragonxlite-cli` in non-interactive mode by passing the command you want to run as an argument. For example, `silentdragonxlite-cli addresses` will list all wallet addresses and exit.
|
||||
Run `silentdragonxlite-cli help` to see a list of all commands.
|
||||
|
||||
## Privacy
|
||||
* While all the keys and transaction detection happens on the client, the server can learn what blocks contain your shielded transactions.
|
||||
* The server also learns other metadata about you like your ip address etc...
|
||||
* Also remember that t-addresses don't provide any privacy protection.
|
||||
|
||||
## Notes:
|
||||
* If you want to run your own server, please see [SilentDragonXLite-cli lightwalletd](https://git.hush.is/hush/lightwalletd), and then run `./silentdragonxlite-cli --server http://127.0.0.1:9067`. You might also need to pass `--dangerous` if you are using a self-signed TLS certificate.
|
||||
|
||||
* The log file is in `~/.silentdragonxlite/silentdragonxlite-cli.debug.log`. Wallet is stored in `~/.silentdragonxlite/silentdragonxlite-cli.dat`
|
||||
|
||||
### Note Management
|
||||
silentdragonxlite does automatic note and utxo management, which means it doesn't allow you to manually select which address to send outgoing transactions from. It follows these principles:
|
||||
* Defaults to sending shielded transactions, even if you're sending to a transparent address
|
||||
* Sapling funds need at least 2 confirmations before they can be spent
|
||||
* Can select funds from multiple shielded addresses in the same transaction
|
||||
* Will automatically shield your transparent funds at the first opportunity
|
||||
* When sending an outgoing transaction to a shielded address, silentdragonxlite can decide to use the transaction to additionally shield your transparent funds (i.e., send your transparent funds to your own shielded address in the same transaction)
|
||||
|
||||
## Compiling from source
|
||||
|
||||
#### Pre-requisites
|
||||
|
||||
|
||||
|
||||
* You need Rust and how you install it will depend on your version of Linux. Below are well known rust versions tested on common Linux distributions.
|
||||
|
||||
| Linux Version | Rust Version Tested | Command to install |
|
||||
|---------------|--------|---------------------------|
|
||||
| Ubuntu 18.04 | 1.47.0 | [USE RUSTUP](https://www.rust-lang.org/tools/install) |
|
||||
| Ubuntu 20.04 | 1.57.0 | sudo apt install rust-all |
|
||||
| Debian 11 | 1.50.0 | [USE RUSTUP](https://www.rust-lang.org/tools/install) |
|
||||
| Arch Linux | 1.56.0 | pacman -S rustc cargo |
|
||||
|
||||
* Debian 11 comes with a much older rust compiler (1.48.0) and so you want to use rustup with Debian and install at least 1.50.0.
|
||||
* If you're using another Linux distro, then consult their package manager for rustc and cargo, but if it's tool old then you want to [use Rustup](https://www.rust-lang.org/tools/install) to install at least 1.50.0.
|
||||
* The build will fail if you do not have `rustfmt` binary, which is included when you use `rustup` but may not be included in via operating system packages. Using `rustup` is recommended
|
||||
|
||||
To securely install rustup by compiling it yourself:
|
||||
|
||||
```
|
||||
git clone https://github.com/rust-lang/rustup
|
||||
cd rustup
|
||||
cargo run --release
|
||||
```
|
||||
|
||||
The above avoids piping the output of curl to bash (bad idea) and avoids using binaries. It will take a few minutes longer but is the better solution.
|
||||
|
||||
|
||||
#### The compilation
|
||||
|
||||
Run the following commands to compile on your computer.
|
||||
|
||||
```shell script
|
||||
git clone https://git.hush.is/dragonx/silentdragonxlite-cli
|
||||
cd silentdragonxlite-cli
|
||||
cargo build --release
|
||||
./target/release/silentdragonxlite-cli
|
||||
```
|
||||
|
||||
#### Or build with make
|
||||
|
||||
Alternatively, you can use the new makefile to build
|
||||
|
||||
```shell script
|
||||
make help
|
||||
make build
|
||||
```
|
||||
|
||||
## Options
|
||||
Here are some CLI arguments you can pass to `silentdragonxlite-cli`. Please run `silentdragonxlite-cli --help` for the full list.
|
||||
|
||||
* `--server`: Connect to a custom SilentDragonXLite lightwalletd server.
|
||||
* Example: `./silentdragonxlite-cli --server 127.0.0.1:9067`
|
||||
* Example: `./silentdragonxlite-cli --server lite.dragonx.is`
|
||||
* `--seed`: Restore a wallet from a seed phrase. **Note** that this will fail if there is an existing wallet. Delete (or move) any existing wallet to restore from the 24-word seed phrase
|
||||
* Example: `./silentdragonxlite-cli --seed "twenty four words seed phrase"`
|
||||
* `--recover`: Attempt to recover the seed phrase from a corrupted wallet
|
||||
* `-n, --nosync`: By default, silentdragonxlite-cli will sync the wallet at startup, so use this option to prevent the automatic sync at startup
|
||||
|
||||
### Support
|
||||
|
||||
For support or other questions, join us on [Telegram](https://dragonx.is/tg) or [file an issue](https://git.hush.is/dragonx/silentdragonxlite-cli/issues).
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright The Hush Developers 2019-2024
|
||||
|
||||
## License
|
||||
|
||||
GPLv3 or later
|
||||
# SilentDragonXLite CLI
|
||||
|
||||
`silentdragonxlite-cli` is a command line SilentDragonXLite light client. To use it, download the latest binary from the releases page and run `./silentdragonxlite-cli` or compile it yourself as documented below.
|
||||
|
||||
This will launch the interactive prompt. Type `help` to get a list of commands
|
||||
|
||||
## Running in non-interactive mode:
|
||||
You can also run `silentdragonxlite-cli` in non-interactive mode by passing the command you want to run as an argument. For example, `silentdragonxlite-cli addresses` will list all wallet addresses and exit.
|
||||
Run `silentdragonxlite-cli help` to see a list of all commands.
|
||||
|
||||
## Privacy
|
||||
* While all the keys and transaction detection happens on the client, the server can learn what blocks contain your shielded transactions.
|
||||
* The server also learns other metadata about you like your ip address etc...
|
||||
* Also remember that t-addresses don't provide any privacy protection.
|
||||
|
||||
## Notes:
|
||||
* If you want to run your own server, please see [SilentDragonXLite-cli lightwalletd](https://git.hush.is/hush/lightwalletd), and then run `./silentdragonxlite-cli --server http://127.0.0.1:9067`. You might also need to pass `--dangerous` if you are using a self-signed TLS certificate.
|
||||
|
||||
* The log file is in `~/.silentdragonxlite/silentdragonxlite-cli.debug.log`. Wallet is stored in `~/.silentdragonxlite/silentdragonxlite-cli.dat`
|
||||
|
||||
### Note Management
|
||||
silentdragonxlite does automatic note and utxo management, which means it doesn't allow you to manually select which address to send outgoing transactions from. It follows these principles:
|
||||
* Defaults to sending shielded transactions, even if you're sending to a transparent address
|
||||
* Sapling funds need at least 2 confirmations before they can be spent
|
||||
* Can select funds from multiple shielded addresses in the same transaction
|
||||
* Will automatically shield your transparent funds at the first opportunity
|
||||
* When sending an outgoing transaction to a shielded address, silentdragonxlite can decide to use the transaction to additionally shield your transparent funds (i.e., send your transparent funds to your own shielded address in the same transaction)
|
||||
|
||||
## Compiling from source
|
||||
|
||||
#### Pre-requisites
|
||||
|
||||
|
||||
|
||||
* You need Rust and how you install it will depend on your version of Linux. Below are well known rust versions tested on common Linux distributions.
|
||||
|
||||
| Linux Version | Rust Version Tested | Command to install |
|
||||
|---------------|--------|---------------------------|
|
||||
| Ubuntu 18.04 | 1.47.0 | [USE RUSTUP](https://www.rust-lang.org/tools/install) |
|
||||
| Ubuntu 20.04 | 1.57.0 | sudo apt install rust-all |
|
||||
| Debian 11 | 1.50.0 | [USE RUSTUP](https://www.rust-lang.org/tools/install) |
|
||||
| Arch Linux | 1.56.0 | pacman -S rustc cargo |
|
||||
|
||||
* Debian 11 comes with a much older rust compiler (1.48.0) and so you want to use rustup with Debian and install at least 1.50.0.
|
||||
* If you're using another Linux distro, then consult their package manager for rustc and cargo, but if it's tool old then you want to [use Rustup](https://www.rust-lang.org/tools/install) to install at least 1.50.0.
|
||||
* The build will fail if you do not have `rustfmt` binary, which is included when you use `rustup` but may not be included in via operating system packages. Using `rustup` is recommended
|
||||
|
||||
To securely install rustup by compiling it yourself:
|
||||
|
||||
```
|
||||
git clone https://github.com/rust-lang/rustup
|
||||
cd rustup
|
||||
cargo run --release
|
||||
```
|
||||
|
||||
The above avoids piping the output of curl to bash (bad idea) and avoids using binaries. It will take a few minutes longer but is the better solution.
|
||||
|
||||
|
||||
#### The compilation
|
||||
|
||||
Run the following commands to compile on your computer.
|
||||
|
||||
```shell script
|
||||
git clone https://git.hush.is/dragonx/silentdragonxlite-cli
|
||||
cd silentdragonxlite-cli
|
||||
cargo build --release
|
||||
./target/release/silentdragonxlite-cli
|
||||
```
|
||||
|
||||
#### Or build with make
|
||||
|
||||
Alternatively, you can use the new makefile to build
|
||||
|
||||
```shell script
|
||||
make help
|
||||
make build
|
||||
```
|
||||
|
||||
## Options
|
||||
Here are some CLI arguments you can pass to `silentdragonxlite-cli`. Please run `silentdragonxlite-cli --help` for the full list.
|
||||
|
||||
* `--server`: Connect to a custom SilentDragonXLite lightwalletd server.
|
||||
* Example: `./silentdragonxlite-cli --server 127.0.0.1:9067`
|
||||
* Example: `./silentdragonxlite-cli --server lite.dragonx.is`
|
||||
* `--seed`: Restore a wallet from a seed phrase. **Note** that this will fail if there is an existing wallet. Delete (or move) any existing wallet to restore from the 24-word seed phrase
|
||||
* Example: `./silentdragonxlite-cli --seed "twenty four words seed phrase"`
|
||||
* `--recover`: Attempt to recover the seed phrase from a corrupted wallet
|
||||
* `-n, --nosync`: By default, silentdragonxlite-cli will sync the wallet at startup, so use this option to prevent the automatic sync at startup
|
||||
|
||||
### Support
|
||||
|
||||
For support or other questions, join us on [Telegram](https://dragonx.is/tg) or [file an issue](https://git.hush.is/dragonx/silentdragonxlite-cli/issues).
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright The Hush Developers 2019-2024
|
||||
|
||||
## License
|
||||
|
||||
GPLv3 or later
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
[package]
|
||||
name = "silentdragonxlite-cli"
|
||||
version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rustyline = "5.0.2"
|
||||
clap = "2.33"
|
||||
log = "0.4"
|
||||
log4rs = "0.8.3"
|
||||
shellwords = "1.0.0"
|
||||
json = "0.12.0"
|
||||
http = "0.2"
|
||||
byteorder = "1"
|
||||
tiny-bip39 = "0.6.2"
|
||||
|
||||
silentdragonxlitelib = { path = "../lib/" }
|
||||
|
||||
[package]
|
||||
name = "silentdragonxlite-cli"
|
||||
version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rustyline = "5.0.2"
|
||||
clap = "2.33"
|
||||
log = "0.4"
|
||||
log4rs = "0.8.3"
|
||||
shellwords = "1.0.0"
|
||||
json = "0.12.0"
|
||||
http = "0.2"
|
||||
byteorder = "1"
|
||||
tiny-bip39 = "0.6.2"
|
||||
|
||||
silentdragonxlitelib = { path = "../lib/" }
|
||||
|
||||
|
||||
524
cli/src/lib.rs
524
cli/src/lib.rs
@@ -1,262 +1,262 @@
|
||||
use std::io::{self};
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
|
||||
use log::{info, error};
|
||||
|
||||
use silentdragonxlitelib::{commands,
|
||||
lightclient::{LightClient, LightClientConfig},
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! configure_clapapp {
|
||||
( $freshapp: expr ) => {
|
||||
$freshapp.version("1.0.0")
|
||||
.arg(Arg::with_name("dangerous")
|
||||
.long("dangerous")
|
||||
.help("Disable server TLS certificate verification. Use this if you're running a local lightwalletd with a self-signed certificate. WARNING: This is dangerous, don't use it with a server that is not your own.")
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("nosync")
|
||||
.help("By default, Silentdragonlite-cli will sync the wallet at startup. Pass --nosync to prevent the automatic sync at startup.")
|
||||
.long("nosync")
|
||||
.short("n")
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("recover")
|
||||
.long("recover")
|
||||
.help("Attempt to recover the seed from the wallet")
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("password")
|
||||
.long("password")
|
||||
.help("When recovering seed, specify a password for the encrypted wallet")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("seed")
|
||||
.short("s")
|
||||
.long("seed")
|
||||
.value_name("seed_phrase")
|
||||
.help("Create a new wallet with the given 24-word seed phrase. Will fail if wallet already exists")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("birthday")
|
||||
.long("birthday")
|
||||
.value_name("birthday")
|
||||
.help("Specify wallet birthday when restoring from seed. This is the earlist block height where the wallet has a transaction.")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("server")
|
||||
.long("server")
|
||||
.value_name("server")
|
||||
.help("Lightwalletd server to connect to.")
|
||||
.takes_value(true)
|
||||
.default_value(lightclient::DEFAULT_SERVER))
|
||||
.arg(Arg::with_name("COMMAND")
|
||||
.help("Command to execute. If a command is not specified, Silentdragonlite-cli will start in interactive mode.")
|
||||
.required(false)
|
||||
.index(1))
|
||||
.arg(Arg::with_name("PARAMS")
|
||||
.help("Params to execute command with. Run the 'help' command to get usage help.")
|
||||
.required(false)
|
||||
.multiple(true))
|
||||
};
|
||||
}
|
||||
|
||||
/// This function is only tested against Linux.
|
||||
pub fn report_permission_error() {
|
||||
let user = std::env::var("USER").expect(
|
||||
"Unexpected error reading value of $USER!");
|
||||
let home = std::env::var("HOME").expect(
|
||||
"Unexpected error reading value of $HOME!");
|
||||
let current_executable = std::env::current_exe()
|
||||
.expect("Unexpected error reporting executable path!");
|
||||
eprintln!("USER: {}", user);
|
||||
eprintln!("HOME: {}", home);
|
||||
eprintln!("Executable: {}", current_executable.display());
|
||||
if home == "/" {
|
||||
eprintln!("User {} must have permission to write to '{}.silentdragonxlite/' .",
|
||||
user,
|
||||
home);
|
||||
} else {
|
||||
eprintln!("User {} must have permission to write to '{}/.silentdragonxlite/' .",
|
||||
user,
|
||||
home);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, birthday: u64, first_sync: bool, print_updates: bool)
|
||||
-> io::Result<(Sender<(String, Vec<String>)>, Receiver<String>)> {
|
||||
// Try to get the configuration
|
||||
let (config, latest_block_height) = LightClientConfig::create(server.clone(), dangerous)?;
|
||||
|
||||
let lightclient = match seed {
|
||||
Some(phrase) => Arc::new(LightClient::new_from_phrase(phrase, &config, birthday,0, false)?),
|
||||
None => {
|
||||
if config.wallet_exists() {
|
||||
Arc::new(LightClient::read_from_disk(&config)?)
|
||||
} else {
|
||||
println!("Creating a new wallet");
|
||||
Arc::new(LightClient::new(&config, latest_block_height)?)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize logging
|
||||
lightclient.init_logging()?;
|
||||
|
||||
// Print startup Messages
|
||||
info!(""); // Blank line
|
||||
info!("Starting Silentdragonlite-CLI");
|
||||
info!("Light Client config {:?}", config);
|
||||
|
||||
if print_updates {
|
||||
println!("Lightclient connecting to {}", config.server);
|
||||
}
|
||||
|
||||
// At startup, run a sync.
|
||||
if first_sync {
|
||||
let update = lightclient.do_sync(true);
|
||||
if print_updates {
|
||||
match update {
|
||||
Ok(j) => {
|
||||
println!("{}", j.pretty(2));
|
||||
},
|
||||
Err(e) => println!("{}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start the command loop
|
||||
let (command_tx, resp_rx) = command_loop(lightclient.clone());
|
||||
|
||||
Ok((command_tx, resp_rx))
|
||||
}
|
||||
|
||||
pub fn start_interactive(command_tx: Sender<(String, Vec<String>)>, resp_rx: Receiver<String>) {
|
||||
// `()` can be used when no completer is required
|
||||
let mut rl = rustyline::Editor::<()>::new();
|
||||
|
||||
println!("Ready!");
|
||||
|
||||
let send_command = |cmd: String, args: Vec<String>| -> String {
|
||||
command_tx.send((cmd.clone(), args)).unwrap();
|
||||
match resp_rx.recv() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
let e = format!("Error executing command {}: {}", cmd, e);
|
||||
eprintln!("{}", e);
|
||||
error!("{}", e);
|
||||
return "".to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let info = send_command("info".to_string(), vec![]);
|
||||
let chain_name = json::parse(&info).unwrap()["chain_name"].as_str().unwrap().to_string();
|
||||
|
||||
loop {
|
||||
// Read the height first
|
||||
let height = json::parse(&send_command("height".to_string(), vec!["false".to_string()])).unwrap()["height"].as_i64().unwrap();
|
||||
|
||||
let readline = rl.readline(&format!("({}) Block:{} (type 'help') >> ",
|
||||
chain_name, height));
|
||||
match readline {
|
||||
Ok(line) => {
|
||||
rl.add_history_entry(line.as_str());
|
||||
// Parse command line arguments
|
||||
let mut cmd_args = match shellwords::split(&line) {
|
||||
Ok(args) => args,
|
||||
Err(_) => {
|
||||
println!("Mismatched Quotes");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if cmd_args.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let cmd = cmd_args.remove(0);
|
||||
let args: Vec<String> = cmd_args;
|
||||
|
||||
println!("{}", send_command(cmd, args));
|
||||
|
||||
// Special check for Quit command.
|
||||
if line == "quit" {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(rustyline::error::ReadlineError::Interrupted) => {
|
||||
println!("CTRL-C");
|
||||
info!("CTRL-C");
|
||||
println!("{}", send_command("save".to_string(), vec![]));
|
||||
break
|
||||
},
|
||||
Err(rustyline::error::ReadlineError::Eof) => {
|
||||
println!("CTRL-D");
|
||||
info!("CTRL-D");
|
||||
println!("{}", send_command("save".to_string(), vec![]));
|
||||
break
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn command_loop(lightclient: Arc<LightClient>) -> (Sender<(String, Vec<String>)>, Receiver<String>) {
|
||||
let (command_tx, command_rx) = channel::<(String, Vec<String>)>();
|
||||
let (resp_tx, resp_rx) = channel::<String>();
|
||||
|
||||
let lc = lightclient.clone();
|
||||
std::thread::spawn(move || {
|
||||
//start mempool_monitor
|
||||
match LightClient::start_mempool_monitor(lc.clone()) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
|
||||
error!("Error starting mempool: {:?}", e);
|
||||
}
|
||||
}
|
||||
loop {
|
||||
match command_rx.recv_timeout(std::time::Duration::from_secs(5 * 60)) {
|
||||
Ok((cmd, args)) => {
|
||||
let args = args.iter().map(|s| s.as_ref()).collect();
|
||||
|
||||
let cmd_response = commands::do_user_command(&cmd, &args, lc.as_ref());
|
||||
resp_tx.send(cmd_response).unwrap();
|
||||
|
||||
if cmd == "quit" {
|
||||
info!("Quit");
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
// Timeout. Do a sync to keep the wallet up-to-date. False to whether to print updates on the console
|
||||
info!("Timeout, doing a sync");
|
||||
match lc.do_sync(false) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {error!("{}", e)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
(command_tx, resp_rx)
|
||||
}
|
||||
|
||||
pub fn attempt_recover_seed(password: Option<String>) {
|
||||
// Create a Light Client Config in an attempt to recover the file.
|
||||
let config = LightClientConfig {
|
||||
server: "0.0.0.0:0".parse().unwrap(),
|
||||
chain_name: "main".to_string(),
|
||||
sapling_activation_height: 0,
|
||||
consensus_branch_id: "000000".to_string(),
|
||||
anchor_offset: 0,
|
||||
no_cert_verification: false,
|
||||
data_dir: None,
|
||||
};
|
||||
|
||||
match LightClient::attempt_recover_seed(&config, password) {
|
||||
Ok(_seed) => println!("Recovered seed "),
|
||||
Err(e) => eprintln!("Failed to recover seed. Error: {}", e)
|
||||
};
|
||||
}
|
||||
use std::io::{self};
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
|
||||
use log::{info, error};
|
||||
|
||||
use silentdragonxlitelib::{commands,
|
||||
lightclient::{LightClient, LightClientConfig},
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! configure_clapapp {
|
||||
( $freshapp: expr ) => {
|
||||
$freshapp.version("1.0.0")
|
||||
.arg(Arg::with_name("dangerous")
|
||||
.long("dangerous")
|
||||
.help("Disable server TLS certificate verification. Use this if you're running a local lightwalletd with a self-signed certificate. WARNING: This is dangerous, don't use it with a server that is not your own.")
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("nosync")
|
||||
.help("By default, Silentdragonlite-cli will sync the wallet at startup. Pass --nosync to prevent the automatic sync at startup.")
|
||||
.long("nosync")
|
||||
.short("n")
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("recover")
|
||||
.long("recover")
|
||||
.help("Attempt to recover the seed from the wallet")
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("password")
|
||||
.long("password")
|
||||
.help("When recovering seed, specify a password for the encrypted wallet")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("seed")
|
||||
.short("s")
|
||||
.long("seed")
|
||||
.value_name("seed_phrase")
|
||||
.help("Create a new wallet with the given 24-word seed phrase. Will fail if wallet already exists")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("birthday")
|
||||
.long("birthday")
|
||||
.value_name("birthday")
|
||||
.help("Specify wallet birthday when restoring from seed. This is the earlist block height where the wallet has a transaction.")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("server")
|
||||
.long("server")
|
||||
.value_name("server")
|
||||
.help("Lightwalletd server to connect to.")
|
||||
.takes_value(true)
|
||||
.default_value(lightclient::DEFAULT_SERVER))
|
||||
.arg(Arg::with_name("COMMAND")
|
||||
.help("Command to execute. If a command is not specified, Silentdragonlite-cli will start in interactive mode.")
|
||||
.required(false)
|
||||
.index(1))
|
||||
.arg(Arg::with_name("PARAMS")
|
||||
.help("Params to execute command with. Run the 'help' command to get usage help.")
|
||||
.required(false)
|
||||
.multiple(true))
|
||||
};
|
||||
}
|
||||
|
||||
/// This function is only tested against Linux.
|
||||
pub fn report_permission_error() {
|
||||
let user = std::env::var("USER").expect(
|
||||
"Unexpected error reading value of $USER!");
|
||||
let home = std::env::var("HOME").expect(
|
||||
"Unexpected error reading value of $HOME!");
|
||||
let current_executable = std::env::current_exe()
|
||||
.expect("Unexpected error reporting executable path!");
|
||||
eprintln!("USER: {}", user);
|
||||
eprintln!("HOME: {}", home);
|
||||
eprintln!("Executable: {}", current_executable.display());
|
||||
if home == "/" {
|
||||
eprintln!("User {} must have permission to write to '{}.silentdragonxlite/' .",
|
||||
user,
|
||||
home);
|
||||
} else {
|
||||
eprintln!("User {} must have permission to write to '{}/.silentdragonxlite/' .",
|
||||
user,
|
||||
home);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, birthday: u64, first_sync: bool, print_updates: bool)
|
||||
-> io::Result<(Sender<(String, Vec<String>)>, Receiver<String>)> {
|
||||
// Try to get the configuration
|
||||
let (config, latest_block_height) = LightClientConfig::create(server.clone(), dangerous)?;
|
||||
|
||||
let lightclient = match seed {
|
||||
Some(phrase) => Arc::new(LightClient::new_from_phrase(phrase, &config, birthday,0, false)?),
|
||||
None => {
|
||||
if config.wallet_exists() {
|
||||
Arc::new(LightClient::read_from_disk(&config)?)
|
||||
} else {
|
||||
println!("Creating a new wallet");
|
||||
Arc::new(LightClient::new(&config, latest_block_height)?)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize logging
|
||||
lightclient.init_logging()?;
|
||||
|
||||
// Print startup Messages
|
||||
info!(""); // Blank line
|
||||
info!("Starting Silentdragonlite-CLI");
|
||||
info!("Light Client config {:?}", config);
|
||||
|
||||
if print_updates {
|
||||
println!("Lightclient connecting to {}", config.server);
|
||||
}
|
||||
|
||||
// At startup, run a sync.
|
||||
if first_sync {
|
||||
let update = lightclient.do_sync(true);
|
||||
if print_updates {
|
||||
match update {
|
||||
Ok(j) => {
|
||||
println!("{}", j.pretty(2));
|
||||
},
|
||||
Err(e) => println!("{}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start the command loop
|
||||
let (command_tx, resp_rx) = command_loop(lightclient.clone());
|
||||
|
||||
Ok((command_tx, resp_rx))
|
||||
}
|
||||
|
||||
pub fn start_interactive(command_tx: Sender<(String, Vec<String>)>, resp_rx: Receiver<String>) {
|
||||
// `()` can be used when no completer is required
|
||||
let mut rl = rustyline::Editor::<()>::new();
|
||||
|
||||
println!("Ready!");
|
||||
|
||||
let send_command = |cmd: String, args: Vec<String>| -> String {
|
||||
command_tx.send((cmd.clone(), args)).unwrap();
|
||||
match resp_rx.recv() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
let e = format!("Error executing command {}: {}", cmd, e);
|
||||
eprintln!("{}", e);
|
||||
error!("{}", e);
|
||||
return "".to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let info = send_command("info".to_string(), vec![]);
|
||||
let chain_name = json::parse(&info).unwrap()["chain_name"].as_str().unwrap().to_string();
|
||||
|
||||
loop {
|
||||
// Read the height first
|
||||
let height = json::parse(&send_command("height".to_string(), vec!["false".to_string()])).unwrap()["height"].as_i64().unwrap();
|
||||
|
||||
let readline = rl.readline(&format!("({}) Block:{} (type 'help') >> ",
|
||||
chain_name, height));
|
||||
match readline {
|
||||
Ok(line) => {
|
||||
rl.add_history_entry(line.as_str());
|
||||
// Parse command line arguments
|
||||
let mut cmd_args = match shellwords::split(&line) {
|
||||
Ok(args) => args,
|
||||
Err(_) => {
|
||||
println!("Mismatched Quotes");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if cmd_args.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let cmd = cmd_args.remove(0);
|
||||
let args: Vec<String> = cmd_args;
|
||||
|
||||
println!("{}", send_command(cmd, args));
|
||||
|
||||
// Special check for Quit command.
|
||||
if line == "quit" {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(rustyline::error::ReadlineError::Interrupted) => {
|
||||
println!("CTRL-C");
|
||||
info!("CTRL-C");
|
||||
println!("{}", send_command("save".to_string(), vec![]));
|
||||
break
|
||||
},
|
||||
Err(rustyline::error::ReadlineError::Eof) => {
|
||||
println!("CTRL-D");
|
||||
info!("CTRL-D");
|
||||
println!("{}", send_command("save".to_string(), vec![]));
|
||||
break
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn command_loop(lightclient: Arc<LightClient>) -> (Sender<(String, Vec<String>)>, Receiver<String>) {
|
||||
let (command_tx, command_rx) = channel::<(String, Vec<String>)>();
|
||||
let (resp_tx, resp_rx) = channel::<String>();
|
||||
|
||||
let lc = lightclient.clone();
|
||||
std::thread::spawn(move || {
|
||||
//start mempool_monitor
|
||||
match LightClient::start_mempool_monitor(lc.clone()) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
|
||||
error!("Error starting mempool: {:?}", e);
|
||||
}
|
||||
}
|
||||
loop {
|
||||
match command_rx.recv_timeout(std::time::Duration::from_secs(5 * 60)) {
|
||||
Ok((cmd, args)) => {
|
||||
let args = args.iter().map(|s| s.as_ref()).collect();
|
||||
|
||||
let cmd_response = commands::do_user_command(&cmd, &args, lc.as_ref());
|
||||
resp_tx.send(cmd_response).unwrap();
|
||||
|
||||
if cmd == "quit" {
|
||||
info!("Quit");
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
// Timeout. Do a sync to keep the wallet up-to-date. False to whether to print updates on the console
|
||||
info!("Timeout, doing a sync");
|
||||
match lc.do_sync(false) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {error!("{}", e)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
(command_tx, resp_rx)
|
||||
}
|
||||
|
||||
pub fn attempt_recover_seed(password: Option<String>) {
|
||||
// Create a Light Client Config in an attempt to recover the file.
|
||||
let config = LightClientConfig {
|
||||
server: "0.0.0.0:0".parse().unwrap(),
|
||||
chain_name: "main".to_string(),
|
||||
sapling_activation_height: 0,
|
||||
consensus_branch_id: "000000".to_string(),
|
||||
anchor_offset: 0,
|
||||
no_cert_verification: false,
|
||||
data_dir: None,
|
||||
};
|
||||
|
||||
match LightClient::attempt_recover_seed(&config, password) {
|
||||
Ok(_seed) => println!("Recovered seed "),
|
||||
Err(e) => eprintln!("Failed to recover seed. Error: {}", e)
|
||||
};
|
||||
}
|
||||
|
||||
186
cli/src/main.rs
186
cli/src/main.rs
@@ -1,93 +1,93 @@
|
||||
use silentdragonxlitelib::lightclient::{self, LightClientConfig};
|
||||
use silentdragonxlite_cli::{configure_clapapp,
|
||||
report_permission_error,
|
||||
startup,
|
||||
start_interactive,
|
||||
attempt_recover_seed};
|
||||
//version::VERSION
|
||||
use log::error;
|
||||
|
||||
pub fn main() {
|
||||
// Get command line arguments
|
||||
use clap::{App, Arg};
|
||||
let fresh_app = App::new("SilentDragonXLite CLI");
|
||||
let configured_app = configure_clapapp!(fresh_app);
|
||||
let matches = configured_app.get_matches();
|
||||
|
||||
if matches.is_present("recover") {
|
||||
// Create a Light Client Config in an attempt to recover the file.
|
||||
attempt_recover_seed(matches.value_of("password").map(|s| s.to_string()));
|
||||
return;
|
||||
}
|
||||
|
||||
let command = matches.value_of("COMMAND");
|
||||
let params = matches.values_of("PARAMS").map(|v| v.collect()).or(Some(vec![])).unwrap();
|
||||
|
||||
let maybe_server = matches.value_of("server").map(|s| s.to_string());
|
||||
|
||||
let seed = matches.value_of("seed").map(|s| s.to_string());
|
||||
let maybe_birthday = matches.value_of("birthday");
|
||||
|
||||
if seed.is_some() && maybe_birthday.is_none() {
|
||||
eprintln!("ERROR!");
|
||||
eprintln!("Please specify the wallet birthday (eg. '--birthday 600000') to restore from seed.");
|
||||
eprintln!("This should be the block height where the wallet was created. If you don't remember the block height, you can pass '--birthday 0' to scan from the start of the blockchain.");
|
||||
return;
|
||||
}
|
||||
|
||||
let birthday = match maybe_birthday.unwrap_or("0").parse::<u64>() {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
eprintln!("Couldn't parse birthday. This should be a block number. Error={}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let server = LightClientConfig::get_server_or_default(maybe_server);
|
||||
|
||||
// Test to make sure the server has all of scheme, host and port
|
||||
if server.scheme_str().is_none() || server.host().is_none() || server.port().is_none() {
|
||||
eprintln!("Please provide the --server parameter as [scheme]://[host]:[port].\nYou provided: {}", server);
|
||||
return;
|
||||
}
|
||||
|
||||
let dangerous = matches.is_present("dangerous");
|
||||
let nosync = matches.is_present("nosync");
|
||||
let (command_tx, resp_rx) = match startup(server, dangerous, seed, birthday, !nosync, command.is_none()) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
let emsg = format!("Error during startup:{}\nIf you repeatedly run into this issue, you might have to restore your wallet from your seed phrase.", e);
|
||||
eprintln!("{}", emsg);
|
||||
error!("{}", emsg);
|
||||
if cfg!(target_os = "unix" ) {
|
||||
match e.raw_os_error() {
|
||||
Some(13) => report_permission_error(),
|
||||
_ => {},
|
||||
}
|
||||
};
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if command.is_none() {
|
||||
start_interactive(command_tx, resp_rx);
|
||||
} else {
|
||||
command_tx.send(
|
||||
(command.unwrap().to_string(),
|
||||
params.iter().map(|s| s.to_string()).collect::<Vec<String>>()))
|
||||
.unwrap();
|
||||
|
||||
match resp_rx.recv() {
|
||||
Ok(s) => println!("{}", s),
|
||||
Err(e) => {
|
||||
let e = format!("Error executing command {}: {}", command.unwrap(), e);
|
||||
eprintln!("{}", e);
|
||||
error!("{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Save before exit
|
||||
command_tx.send(("save".to_string(), vec![])).unwrap();
|
||||
resp_rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
use silentdragonxlitelib::lightclient::{self, LightClientConfig};
|
||||
use silentdragonxlite_cli::{configure_clapapp,
|
||||
report_permission_error,
|
||||
startup,
|
||||
start_interactive,
|
||||
attempt_recover_seed};
|
||||
//version::VERSION
|
||||
use log::error;
|
||||
|
||||
pub fn main() {
|
||||
// Get command line arguments
|
||||
use clap::{App, Arg};
|
||||
let fresh_app = App::new("SilentDragonXLite CLI");
|
||||
let configured_app = configure_clapapp!(fresh_app);
|
||||
let matches = configured_app.get_matches();
|
||||
|
||||
if matches.is_present("recover") {
|
||||
// Create a Light Client Config in an attempt to recover the file.
|
||||
attempt_recover_seed(matches.value_of("password").map(|s| s.to_string()));
|
||||
return;
|
||||
}
|
||||
|
||||
let command = matches.value_of("COMMAND");
|
||||
let params = matches.values_of("PARAMS").map(|v| v.collect()).or(Some(vec![])).unwrap();
|
||||
|
||||
let maybe_server = matches.value_of("server").map(|s| s.to_string());
|
||||
|
||||
let seed = matches.value_of("seed").map(|s| s.to_string());
|
||||
let maybe_birthday = matches.value_of("birthday");
|
||||
|
||||
if seed.is_some() && maybe_birthday.is_none() {
|
||||
eprintln!("ERROR!");
|
||||
eprintln!("Please specify the wallet birthday (eg. '--birthday 600000') to restore from seed.");
|
||||
eprintln!("This should be the block height where the wallet was created. If you don't remember the block height, you can pass '--birthday 0' to scan from the start of the blockchain.");
|
||||
return;
|
||||
}
|
||||
|
||||
let birthday = match maybe_birthday.unwrap_or("0").parse::<u64>() {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
eprintln!("Couldn't parse birthday. This should be a block number. Error={}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let server = LightClientConfig::get_server_or_default(maybe_server);
|
||||
|
||||
// Test to make sure the server has all of scheme, host and port
|
||||
if server.scheme_str().is_none() || server.host().is_none() || server.port().is_none() {
|
||||
eprintln!("Please provide the --server parameter as [scheme]://[host]:[port].\nYou provided: {}", server);
|
||||
return;
|
||||
}
|
||||
|
||||
let dangerous = matches.is_present("dangerous");
|
||||
let nosync = matches.is_present("nosync");
|
||||
let (command_tx, resp_rx) = match startup(server, dangerous, seed, birthday, !nosync, command.is_none()) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
let emsg = format!("Error during startup:{}\nIf you repeatedly run into this issue, you might have to restore your wallet from your seed phrase.", e);
|
||||
eprintln!("{}", emsg);
|
||||
error!("{}", emsg);
|
||||
if cfg!(target_os = "unix" ) {
|
||||
match e.raw_os_error() {
|
||||
Some(13) => report_permission_error(),
|
||||
_ => {},
|
||||
}
|
||||
};
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if command.is_none() {
|
||||
start_interactive(command_tx, resp_rx);
|
||||
} else {
|
||||
command_tx.send(
|
||||
(command.unwrap().to_string(),
|
||||
params.iter().map(|s| s.to_string()).collect::<Vec<String>>()))
|
||||
.unwrap();
|
||||
|
||||
match resp_rx.recv() {
|
||||
Ok(s) => println!("{}", s),
|
||||
Err(e) => {
|
||||
let e = format!("Error executing command {}: {}", command.unwrap(), e);
|
||||
eprintln!("{}", e);
|
||||
error!("{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Save before exit
|
||||
command_tx.send(("save".to_string(), vec![])).unwrap();
|
||||
resp_rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
pub const VERSION:&str = "1.1.2";
|
||||
pub const VERSION:&str = "1.1.2";
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
FROM ubuntu:16.04
|
||||
LABEL Description="Rust compile env for Linux + Windows (cross)"
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -y build-essential mingw-w64 gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf curl vim wget
|
||||
|
||||
# Get Rust
|
||||
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
|
||||
RUN rustup target add x86_64-pc-windows-gnu
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||
|
||||
# Append the linker to the cargo config for Windows cross compile
|
||||
RUN echo "[target.x86_64-pc-windows-gnu]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/x86_64-w64-mingw32-gcc'" >> /root/.cargo/config
|
||||
|
||||
RUN echo "[target.aarch64-unknown-linux-gnu]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/aarch64-linux-gnu-gcc'" >> /root/.cargo/config
|
||||
|
||||
RUN echo "[target.armv7-unknown-linux-gnueabihf]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/arm-linux-gnueabihf-gcc'" >> /root/.cargo/config
|
||||
|
||||
ENV CC_x86_64_unknown_linux_musl="gcc"
|
||||
ENV CC_aarch64_unknown_linux_gnu="aarch64-linux-gnu-gcc"
|
||||
ENV CC_armv7_unknown_linux_gnueabhihf="arm-linux-gnueabihf-gcc"
|
||||
|
||||
# This is a bug fix for the windows cross compiler for Rust.
|
||||
RUN cp /usr/x86_64-w64-mingw32/lib/crt2.o /root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o
|
||||
|
||||
# For windows cross compilation, use a pre-build binary. Remember to set the
|
||||
# SODIUM_LIB_DIR for windows cross compilation
|
||||
RUN cd /opt && wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.17-mingw.tar.gz && \
|
||||
tar xvf libsodium-1.0.17-mingw.tar.gz
|
||||
|
||||
RUN apt install -y git
|
||||
|
||||
# Cargo fetch the dependencies so we don't download them over and over again
|
||||
RUN cd /tmp && git clone https://github.com/adityapk00/silentdragonlite-light-cli.git && \
|
||||
cd silentdragonlite-light-cli && \
|
||||
cargo fetch && \
|
||||
cd /tmp && rm -rf silentdragonlite-light-cli
|
||||
FROM ubuntu:16.04
|
||||
LABEL Description="Rust compile env for Linux + Windows (cross)"
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -y build-essential mingw-w64 gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf curl vim wget
|
||||
|
||||
# Get Rust
|
||||
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
|
||||
RUN rustup target add x86_64-pc-windows-gnu
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||
|
||||
# Append the linker to the cargo config for Windows cross compile
|
||||
RUN echo "[target.x86_64-pc-windows-gnu]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/x86_64-w64-mingw32-gcc'" >> /root/.cargo/config
|
||||
|
||||
RUN echo "[target.aarch64-unknown-linux-gnu]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/aarch64-linux-gnu-gcc'" >> /root/.cargo/config
|
||||
|
||||
RUN echo "[target.armv7-unknown-linux-gnueabihf]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/arm-linux-gnueabihf-gcc'" >> /root/.cargo/config
|
||||
|
||||
ENV CC_x86_64_unknown_linux_musl="gcc"
|
||||
ENV CC_aarch64_unknown_linux_gnu="aarch64-linux-gnu-gcc"
|
||||
ENV CC_armv7_unknown_linux_gnueabhihf="arm-linux-gnueabihf-gcc"
|
||||
|
||||
# This is a bug fix for the windows cross compiler for Rust.
|
||||
RUN cp /usr/x86_64-w64-mingw32/lib/crt2.o /root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o
|
||||
|
||||
# For windows cross compilation, use a pre-build binary. Remember to set the
|
||||
# SODIUM_LIB_DIR for windows cross compilation
|
||||
RUN cd /opt && wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.17-mingw.tar.gz && \
|
||||
tar xvf libsodium-1.0.17-mingw.tar.gz
|
||||
|
||||
RUN apt install -y git
|
||||
|
||||
# Cargo fetch the dependencies so we don't download them over and over again
|
||||
RUN cd /tmp && git clone https://github.com/adityapk00/silentdragonlite-light-cli.git && \
|
||||
cd silentdragonlite-light-cli && \
|
||||
cargo fetch && \
|
||||
cd /tmp && rm -rf silentdragonlite-light-cli
|
||||
|
||||
160
lib/Cargo.toml
160
lib/Cargo.toml
@@ -1,80 +1,80 @@
|
||||
[package]
|
||||
name = "silentdragonxlitelib"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
default = ["embed_params"]
|
||||
embed_params = []
|
||||
|
||||
[dependencies]
|
||||
base58 = "0.1.0"
|
||||
bs58 = { version = "0.2", features = ["check"] }
|
||||
log = "0.4"
|
||||
log4rs = "0.8.3"
|
||||
dirs = "2.0.2"
|
||||
http = "0.2"
|
||||
hex = "0.3"
|
||||
protobuf = "2"
|
||||
byteorder = "1"
|
||||
json = "0.12.0"
|
||||
tiny-bip39 = "0.6.2"
|
||||
secp256k1 = "=0.15.0"
|
||||
sha2 = "0.8.0"
|
||||
ripemd160 = "0.8.0"
|
||||
lazy_static = "1.2.0"
|
||||
rust-embed = { version = "5.1.0", features = ["debug-embed"] }
|
||||
rand = "0.7.2"
|
||||
sodiumoxide = "0.2.5"
|
||||
ring = "0.16.9"
|
||||
libflate = "0.1"
|
||||
subtle = "2"
|
||||
threadpool = "1.8.0"
|
||||
num_cpus = "1.13.0"
|
||||
|
||||
tonic = { version = "0.1.1", features = ["tls", "tls-roots"] }
|
||||
bytes = "0.4"
|
||||
prost = "0.6"
|
||||
prost-types = "0.6"
|
||||
tokio = { version = "0.2", features = ["rt-threaded", "time", "stream", "fs", "macros", "uds", "full"] }
|
||||
tokio-rustls = { version = "0.12.1", features = ["dangerous_configuration"] }
|
||||
webpki = "0.21.0"
|
||||
webpki-roots = "0.18.0"
|
||||
|
||||
[dependencies.bellman]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
default-features = false
|
||||
features = ["groth16"]
|
||||
|
||||
[dependencies.pairing]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
|
||||
[dependencies.zcash_client_backend]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
|
||||
default-features = false
|
||||
|
||||
[dependencies.zcash_primitives]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
default-features = false
|
||||
features = ["transparent-inputs"]
|
||||
|
||||
[dependencies.zcash_proofs]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
default-features = false
|
||||
|
||||
[dependencies.ff]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
features = ["ff_derive"]
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3.7"
|
||||
[package]
|
||||
name = "silentdragonxlitelib"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
default = ["embed_params"]
|
||||
embed_params = []
|
||||
|
||||
[dependencies]
|
||||
base58 = "0.1.0"
|
||||
bs58 = { version = "0.2", features = ["check"] }
|
||||
log = "0.4"
|
||||
log4rs = "0.8.3"
|
||||
dirs = "2.0.2"
|
||||
http = "0.2"
|
||||
hex = "0.3"
|
||||
protobuf = "2"
|
||||
byteorder = "1"
|
||||
json = "0.12.0"
|
||||
tiny-bip39 = "0.6.2"
|
||||
secp256k1 = "=0.15.0"
|
||||
sha2 = "0.8.0"
|
||||
ripemd160 = "0.8.0"
|
||||
lazy_static = "1.2.0"
|
||||
rust-embed = { version = "5.1.0", features = ["debug-embed"] }
|
||||
rand = "0.7.2"
|
||||
sodiumoxide = "0.2.5"
|
||||
ring = "0.16.9"
|
||||
libflate = "0.1"
|
||||
subtle = "2"
|
||||
threadpool = "1.8.0"
|
||||
num_cpus = "1.13.0"
|
||||
|
||||
tonic = { version = "0.1.1", features = ["tls", "tls-roots"] }
|
||||
bytes = "0.4"
|
||||
prost = "0.6"
|
||||
prost-types = "0.6"
|
||||
tokio = { version = "0.2", features = ["rt-threaded", "time", "stream", "fs", "macros", "uds", "full"] }
|
||||
tokio-rustls = { version = "0.12.1", features = ["dangerous_configuration"] }
|
||||
webpki = "0.21.0"
|
||||
webpki-roots = "0.18.0"
|
||||
|
||||
[dependencies.bellman]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
default-features = false
|
||||
features = ["groth16"]
|
||||
|
||||
[dependencies.pairing]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
|
||||
[dependencies.zcash_client_backend]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
|
||||
default-features = false
|
||||
|
||||
[dependencies.zcash_primitives]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
default-features = false
|
||||
features = ["transparent-inputs"]
|
||||
|
||||
[dependencies.zcash_proofs]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
default-features = false
|
||||
|
||||
[dependencies.ff]
|
||||
git = "https://git.hush.is/hush/librustzcash.git"
|
||||
rev= "acff1444ec373e9c3e37b47ca95bfd358e45255b"
|
||||
features = ["ff_derive"]
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3.7"
|
||||
|
||||
26
lib/build.rs
26
lib/build.rs
@@ -1,13 +1,13 @@
|
||||
// Copyright The Hush Developers 2019-2022
|
||||
// Released under the GPLv3
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tonic_build::configure()
|
||||
.build_server(false)
|
||||
.compile(
|
||||
&["proto/service.proto", "proto/compact_formats.proto"],
|
||||
&["proto"],
|
||||
)?;
|
||||
println!("cargo:rerun-if-changed=proto/service.proto");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Copyright The Hush Developers 2019-2022
|
||||
// Released under the GPLv3
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tonic_build::configure()
|
||||
.build_server(false)
|
||||
.compile(
|
||||
&["proto/service.proto", "proto/compact_formats.proto"],
|
||||
&["proto"],
|
||||
)?;
|
||||
println!("cargo:rerun-if-changed=proto/service.proto");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "lightwalletd/walletrpc";
|
||||
option swift_prefix = "";
|
||||
|
||||
// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
|
||||
// bytes fields of hashes are in canonical little-endian format.
|
||||
|
||||
// CompactBlock is a packaging of ONLY the data from a block that's needed to:
|
||||
// 1. Detect a payment to your shielded Sapling address
|
||||
// 2. Detect a spend of your shielded Sapling notes
|
||||
// 3. Update your witnesses to generate new Sapling spend proofs.
|
||||
message CompactBlock {
|
||||
uint32 protoVersion = 1; // the version of this wire format, for storage
|
||||
uint64 height = 2; // the height of this block
|
||||
bytes hash = 3; // the ID (hash) of this block, same as in block explorers
|
||||
bytes prevHash = 4; // the ID (hash) of this block's predecessor
|
||||
uint32 time = 5; // Unix epoch time when the block was mined
|
||||
bytes header = 6; // (hash, prevHash, and time) OR (full header)
|
||||
repeated CompactTx vtx = 7; // compact transactions from this block
|
||||
}
|
||||
|
||||
message CompactTx {
|
||||
// Index and hash will allow the receiver to call out to chain
|
||||
// explorers or other data structures to retrieve more information
|
||||
// about this transaction.
|
||||
uint64 index = 1; // the index within the full block
|
||||
bytes hash = 2; // the ID (hash) of this transaction, same as in block explorers
|
||||
|
||||
// The transaction fee: present if server can provide. In the case of a
|
||||
// stateless server and a transaction with transparent inputs, this will be
|
||||
// unset because the calculation requires reference to prior transactions.
|
||||
// in a pure-Sapling context, the fee will be calculable as:
|
||||
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
|
||||
uint32 fee = 3;
|
||||
|
||||
repeated CompactSaplingSpend spends = 4;
|
||||
repeated CompactSaplingOutput outputs = 5;
|
||||
}
|
||||
|
||||
// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash
|
||||
// protocol specification.
|
||||
message CompactSaplingSpend {
|
||||
bytes nf = 1; // nullifier (see the Zcash protocol specification)
|
||||
}
|
||||
|
||||
// output is a Sapling Output Description as described in section 7.4 of the
|
||||
// Zcash protocol spec. Total size is 948.
|
||||
message CompactSaplingOutput {
|
||||
bytes cmu = 1; // note commitment u-coordinate
|
||||
bytes epk = 2; // ephemeral public key
|
||||
bytes ciphertext = 3; // first 52 bytes of ciphertext
|
||||
}
|
||||
|
||||
/*
|
||||
message CompactSpend {
|
||||
bytes nf = 1; // nullifier (see the Zcash protocol specification)
|
||||
}
|
||||
|
||||
message CompactOutput {
|
||||
bytes cmu = 1; // note commitment u-coordinate
|
||||
bytes epk = 2; // ephemeral public key
|
||||
bytes ciphertext = 3; // first 52 bytes of ciphertext
|
||||
}
|
||||
*/
|
||||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "lightwalletd/walletrpc";
|
||||
option swift_prefix = "";
|
||||
|
||||
// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
|
||||
// bytes fields of hashes are in canonical little-endian format.
|
||||
|
||||
// CompactBlock is a packaging of ONLY the data from a block that's needed to:
|
||||
// 1. Detect a payment to your shielded Sapling address
|
||||
// 2. Detect a spend of your shielded Sapling notes
|
||||
// 3. Update your witnesses to generate new Sapling spend proofs.
|
||||
message CompactBlock {
|
||||
uint32 protoVersion = 1; // the version of this wire format, for storage
|
||||
uint64 height = 2; // the height of this block
|
||||
bytes hash = 3; // the ID (hash) of this block, same as in block explorers
|
||||
bytes prevHash = 4; // the ID (hash) of this block's predecessor
|
||||
uint32 time = 5; // Unix epoch time when the block was mined
|
||||
bytes header = 6; // (hash, prevHash, and time) OR (full header)
|
||||
repeated CompactTx vtx = 7; // compact transactions from this block
|
||||
}
|
||||
|
||||
message CompactTx {
|
||||
// Index and hash will allow the receiver to call out to chain
|
||||
// explorers or other data structures to retrieve more information
|
||||
// about this transaction.
|
||||
uint64 index = 1; // the index within the full block
|
||||
bytes hash = 2; // the ID (hash) of this transaction, same as in block explorers
|
||||
|
||||
// The transaction fee: present if server can provide. In the case of a
|
||||
// stateless server and a transaction with transparent inputs, this will be
|
||||
// unset because the calculation requires reference to prior transactions.
|
||||
// in a pure-Sapling context, the fee will be calculable as:
|
||||
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
|
||||
uint32 fee = 3;
|
||||
|
||||
repeated CompactSaplingSpend spends = 4;
|
||||
repeated CompactSaplingOutput outputs = 5;
|
||||
}
|
||||
|
||||
// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash
|
||||
// protocol specification.
|
||||
message CompactSaplingSpend {
|
||||
bytes nf = 1; // nullifier (see the Zcash protocol specification)
|
||||
}
|
||||
|
||||
// output is a Sapling Output Description as described in section 7.4 of the
|
||||
// Zcash protocol spec. Total size is 948.
|
||||
message CompactSaplingOutput {
|
||||
bytes cmu = 1; // note commitment u-coordinate
|
||||
bytes epk = 2; // ephemeral public key
|
||||
bytes ciphertext = 3; // first 52 bytes of ciphertext
|
||||
}
|
||||
|
||||
/*
|
||||
message CompactSpend {
|
||||
bytes nf = 1; // nullifier (see the Zcash protocol specification)
|
||||
}
|
||||
|
||||
message CompactOutput {
|
||||
bytes cmu = 1; // note commitment u-coordinate
|
||||
bytes epk = 2; // ephemeral public key
|
||||
bytes ciphertext = 3; // first 52 bytes of ciphertext
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,170 +1,170 @@
|
||||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "lightwalletd/walletrpc";
|
||||
option swift_prefix = "";
|
||||
import "compact_formats.proto";
|
||||
|
||||
// A BlockID message contains identifiers to select a block: a height or a
|
||||
// hash. If the hash is present it takes precedence.
|
||||
message BlockID {
|
||||
uint64 height = 1;
|
||||
bytes hash = 2;
|
||||
}
|
||||
|
||||
// BlockRange technically allows ranging from hash to hash etc but this is not
|
||||
// currently intended for support, though there is no reason you couldn't do
|
||||
// it. Further permutations are left as an exercise.
|
||||
message BlockRange {
|
||||
BlockID start = 1;
|
||||
BlockID end = 2;
|
||||
}
|
||||
|
||||
// A TxFilter contains the information needed to identify a particular
|
||||
// transaction: either a block and an index, or a direct transaction hash.
|
||||
message TxFilter {
|
||||
BlockID block = 1;
|
||||
uint64 index = 2;
|
||||
bytes hash = 3;
|
||||
}
|
||||
|
||||
// RawTransaction contains the complete transaction data. It also optionally includes
|
||||
// the block height in which the transaction was included
|
||||
message RawTransaction {
|
||||
bytes data = 1;
|
||||
uint64 height = 2;
|
||||
}
|
||||
|
||||
message SendResponse {
|
||||
int32 errorCode = 1;
|
||||
string errorMessage = 2;
|
||||
}
|
||||
|
||||
// Empty placeholder. Someday we may want to specify e.g. a particular chain fork.
|
||||
message ChainSpec {}
|
||||
|
||||
message Empty {}
|
||||
|
||||
message LightdInfo {
|
||||
string version = 1;
|
||||
string vendor = 2;
|
||||
bool taddrSupport = 3;
|
||||
string chainName = 4;
|
||||
uint64 saplingActivationHeight = 5;
|
||||
string consensusBranchId = 6; // This should really be u32 or []byte, but string for readability
|
||||
uint64 blockHeight = 7;
|
||||
uint64 difficulty = 8;
|
||||
uint64 longestchain = 9;
|
||||
uint64 notarized = 10;
|
||||
}
|
||||
message Coinsupply {
|
||||
string result = 1;
|
||||
string coin = 2;
|
||||
uint64 height = 3;
|
||||
uint64 supply = 4;
|
||||
uint64 zfunds = 5;
|
||||
uint64 total = 6;
|
||||
}
|
||||
|
||||
message TransparentAddress {
|
||||
string address = 1;
|
||||
}
|
||||
|
||||
message TransparentAddressBlockFilter {
|
||||
string address = 1;
|
||||
BlockRange range = 2;
|
||||
}
|
||||
|
||||
message Address {
|
||||
string address = 1;
|
||||
}
|
||||
message AddressList {
|
||||
repeated string addresses = 1;
|
||||
}
|
||||
message Balance {
|
||||
int64 valueZat = 1;
|
||||
}
|
||||
|
||||
message Exclude {
|
||||
repeated bytes txid = 1;
|
||||
}
|
||||
|
||||
// The TreeState is derived from the Hush getblockmerkletree rpc.
|
||||
// https://faq.hush.is/rpc/getblockmerkletree.html
|
||||
message TreeState {
|
||||
string network = 1; // "main" or "test"
|
||||
uint64 height = 2; // block height
|
||||
string hash = 3; // block id
|
||||
uint32 time = 4; // Unix epoch time when the block was mined
|
||||
string saplingTree = 5; // sapling commitment tree state
|
||||
}
|
||||
|
||||
// Results are sorted by height, which makes it easy to issue another
|
||||
// request that picks up from where the previous left off.
|
||||
message GetAddressUtxosArg {
|
||||
repeated string addresses = 1;
|
||||
uint64 startHeight = 2;
|
||||
uint32 maxEntries = 3; // zero means unlimited
|
||||
}
|
||||
message GetAddressUtxosReply {
|
||||
string address = 6;
|
||||
bytes txid = 1;
|
||||
int32 index = 2;
|
||||
bytes script = 3;
|
||||
int64 valueZat = 4;
|
||||
uint64 height = 5;
|
||||
}
|
||||
message GetAddressUtxosReplyList {
|
||||
repeated GetAddressUtxosReply addressUtxos = 1;
|
||||
}
|
||||
|
||||
service CompactTxStreamer {
|
||||
// Return the height of the tip of the best chain
|
||||
rpc GetLatestBlock(ChainSpec) returns (BlockID) {}
|
||||
// Return the compact block corresponding to the given block identifier
|
||||
rpc GetBlock(BlockID) returns (CompactBlock) {}
|
||||
// Return a list of consecutive compact blocks
|
||||
rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {}
|
||||
|
||||
// Return the requested full (not compact) transaction (as from zcashd)
|
||||
rpc GetTransaction(TxFilter) returns (RawTransaction) {}
|
||||
// Submit the given transaction to the Zcash network
|
||||
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
|
||||
|
||||
// Return the txids corresponding to the given t-address within the given block range
|
||||
rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {}
|
||||
// wrapper for GetTaddressTxids
|
||||
rpc GetAddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {}
|
||||
rpc GetTaddressBalance(AddressList) returns (Balance) {}
|
||||
rpc GetTaddressBalanceStream(stream Address) returns (Balance) {}
|
||||
|
||||
// Return the compact transactions currently in the mempool; the results
|
||||
// can be a few seconds out of date. If the Exclude list is empty, return
|
||||
// all transactions; otherwise return all *except* those in the Exclude list
|
||||
// (if any); this allows the client to avoid receiving transactions that it
|
||||
// already has (from an earlier call to this rpc). The transaction IDs in the
|
||||
// Exclude list can be shortened to any number of bytes to make the request
|
||||
// more bandwidth-efficient; if two or more transactions in the mempool
|
||||
// match a shortened txid, they are all sent (none is excluded). Transactions
|
||||
// in the exclude list that don't exist in the mempool are ignored.
|
||||
rpc GetMempoolTx(Exclude) returns (stream CompactTx) {}
|
||||
|
||||
// Return a stream of current Mempool transactions. This will keep the output stream open while
|
||||
// there are mempool transactions. It will close the returned stream when a new block is mined.
|
||||
rpc GetMempoolStream(Empty) returns (stream RawTransaction) {}
|
||||
|
||||
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||
// values also (even though they can be obtained using GetBlock).
|
||||
// The block can be specified by either height or hash.
|
||||
rpc GetTreeState(BlockID) returns (TreeState) {}
|
||||
rpc GetLatestTreeState(Empty) returns (TreeState) {}
|
||||
|
||||
rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {}
|
||||
rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {}
|
||||
|
||||
// Return information about this lightwalletd instance and the blockchain
|
||||
rpc GetLightdInfo(Empty) returns (LightdInfo) {}
|
||||
// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production)
|
||||
// rpc Ping(Duration) returns (PingResponse) {}
|
||||
rpc GetCoinsupply(Empty) returns (Coinsupply) {}
|
||||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "lightwalletd/walletrpc";
|
||||
option swift_prefix = "";
|
||||
import "compact_formats.proto";
|
||||
|
||||
// A BlockID message contains identifiers to select a block: a height or a
|
||||
// hash. If the hash is present it takes precedence.
|
||||
message BlockID {
|
||||
uint64 height = 1;
|
||||
bytes hash = 2;
|
||||
}
|
||||
|
||||
// BlockRange technically allows ranging from hash to hash etc but this is not
|
||||
// currently intended for support, though there is no reason you couldn't do
|
||||
// it. Further permutations are left as an exercise.
|
||||
message BlockRange {
|
||||
BlockID start = 1;
|
||||
BlockID end = 2;
|
||||
}
|
||||
|
||||
// A TxFilter contains the information needed to identify a particular
|
||||
// transaction: either a block and an index, or a direct transaction hash.
|
||||
message TxFilter {
|
||||
BlockID block = 1;
|
||||
uint64 index = 2;
|
||||
bytes hash = 3;
|
||||
}
|
||||
|
||||
// RawTransaction contains the complete transaction data. It also optionally includes
|
||||
// the block height in which the transaction was included
|
||||
message RawTransaction {
|
||||
bytes data = 1;
|
||||
uint64 height = 2;
|
||||
}
|
||||
|
||||
message SendResponse {
|
||||
int32 errorCode = 1;
|
||||
string errorMessage = 2;
|
||||
}
|
||||
|
||||
// Empty placeholder. Someday we may want to specify e.g. a particular chain fork.
|
||||
message ChainSpec {}
|
||||
|
||||
message Empty {}
|
||||
|
||||
message LightdInfo {
|
||||
string version = 1;
|
||||
string vendor = 2;
|
||||
bool taddrSupport = 3;
|
||||
string chainName = 4;
|
||||
uint64 saplingActivationHeight = 5;
|
||||
string consensusBranchId = 6; // This should really be u32 or []byte, but string for readability
|
||||
uint64 blockHeight = 7;
|
||||
uint64 difficulty = 8;
|
||||
uint64 longestchain = 9;
|
||||
uint64 notarized = 10;
|
||||
}
|
||||
message Coinsupply {
|
||||
string result = 1;
|
||||
string coin = 2;
|
||||
uint64 height = 3;
|
||||
uint64 supply = 4;
|
||||
uint64 zfunds = 5;
|
||||
uint64 total = 6;
|
||||
}
|
||||
|
||||
message TransparentAddress {
|
||||
string address = 1;
|
||||
}
|
||||
|
||||
message TransparentAddressBlockFilter {
|
||||
string address = 1;
|
||||
BlockRange range = 2;
|
||||
}
|
||||
|
||||
message Address {
|
||||
string address = 1;
|
||||
}
|
||||
message AddressList {
|
||||
repeated string addresses = 1;
|
||||
}
|
||||
message Balance {
|
||||
int64 valueZat = 1;
|
||||
}
|
||||
|
||||
message Exclude {
|
||||
repeated bytes txid = 1;
|
||||
}
|
||||
|
||||
// The TreeState is derived from the Hush getblockmerkletree rpc.
|
||||
// https://faq.hush.is/rpc/getblockmerkletree.html
|
||||
message TreeState {
|
||||
string network = 1; // "main" or "test"
|
||||
uint64 height = 2; // block height
|
||||
string hash = 3; // block id
|
||||
uint32 time = 4; // Unix epoch time when the block was mined
|
||||
string saplingTree = 5; // sapling commitment tree state
|
||||
}
|
||||
|
||||
// Results are sorted by height, which makes it easy to issue another
|
||||
// request that picks up from where the previous left off.
|
||||
message GetAddressUtxosArg {
|
||||
repeated string addresses = 1;
|
||||
uint64 startHeight = 2;
|
||||
uint32 maxEntries = 3; // zero means unlimited
|
||||
}
|
||||
message GetAddressUtxosReply {
|
||||
string address = 6;
|
||||
bytes txid = 1;
|
||||
int32 index = 2;
|
||||
bytes script = 3;
|
||||
int64 valueZat = 4;
|
||||
uint64 height = 5;
|
||||
}
|
||||
message GetAddressUtxosReplyList {
|
||||
repeated GetAddressUtxosReply addressUtxos = 1;
|
||||
}
|
||||
|
||||
service CompactTxStreamer {
|
||||
// Return the height of the tip of the best chain
|
||||
rpc GetLatestBlock(ChainSpec) returns (BlockID) {}
|
||||
// Return the compact block corresponding to the given block identifier
|
||||
rpc GetBlock(BlockID) returns (CompactBlock) {}
|
||||
// Return a list of consecutive compact blocks
|
||||
rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {}
|
||||
|
||||
// Return the requested full (not compact) transaction (as from zcashd)
|
||||
rpc GetTransaction(TxFilter) returns (RawTransaction) {}
|
||||
// Submit the given transaction to the Zcash network
|
||||
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
|
||||
|
||||
// Return the txids corresponding to the given t-address within the given block range
|
||||
rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {}
|
||||
// wrapper for GetTaddressTxids
|
||||
rpc GetAddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {}
|
||||
rpc GetTaddressBalance(AddressList) returns (Balance) {}
|
||||
rpc GetTaddressBalanceStream(stream Address) returns (Balance) {}
|
||||
|
||||
// Return the compact transactions currently in the mempool; the results
|
||||
// can be a few seconds out of date. If the Exclude list is empty, return
|
||||
// all transactions; otherwise return all *except* those in the Exclude list
|
||||
// (if any); this allows the client to avoid receiving transactions that it
|
||||
// already has (from an earlier call to this rpc). The transaction IDs in the
|
||||
// Exclude list can be shortened to any number of bytes to make the request
|
||||
// more bandwidth-efficient; if two or more transactions in the mempool
|
||||
// match a shortened txid, they are all sent (none is excluded). Transactions
|
||||
// in the exclude list that don't exist in the mempool are ignored.
|
||||
rpc GetMempoolTx(Exclude) returns (stream CompactTx) {}
|
||||
|
||||
// Return a stream of current Mempool transactions. This will keep the output stream open while
|
||||
// there are mempool transactions. It will close the returned stream when a new block is mined.
|
||||
rpc GetMempoolStream(Empty) returns (stream RawTransaction) {}
|
||||
|
||||
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||
// values also (even though they can be obtained using GetBlock).
|
||||
// The block can be specified by either height or hash.
|
||||
rpc GetTreeState(BlockID) returns (TreeState) {}
|
||||
rpc GetLatestTreeState(Empty) returns (TreeState) {}
|
||||
|
||||
rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {}
|
||||
rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {}
|
||||
|
||||
// Return information about this lightwalletd instance and the blockchain
|
||||
rpc GetLightdInfo(Empty) returns (LightdInfo) {}
|
||||
// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production)
|
||||
// rpc Ping(Duration) returns (PingResponse) {}
|
||||
rpc GetCoinsupply(Empty) returns (Coinsupply) {}
|
||||
}
|
||||
1950
lib/src/commands.rs
1950
lib/src/commands.rs
File diff suppressed because it is too large
Load Diff
@@ -1,366 +1,363 @@
|
||||
// Copyright The Hush Developers 2019-2022
|
||||
// Released under the GPLv3
|
||||
use log::{info,error};
|
||||
use std::sync::Arc;
|
||||
use zcash_primitives::transaction::{TxId};
|
||||
|
||||
use crate::grpc_client::{ChainSpec, BlockId, BlockRange, RawTransaction, CompactBlock,
|
||||
TransparentAddressBlockFilter, TxFilter, Empty, LightdInfo, Coinsupply};
|
||||
use tonic::transport::{Channel, ClientTlsConfig};
|
||||
use tokio_rustls::{rustls::ClientConfig};
|
||||
use tonic::{Request};
|
||||
|
||||
use threadpool::ThreadPool;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use crate::PubCertificate;
|
||||
use crate::grpc_client::compact_tx_streamer_client::CompactTxStreamerClient;
|
||||
|
||||
mod danger {
|
||||
use tokio_rustls::rustls;
|
||||
use webpki;
|
||||
|
||||
pub struct NoCertificateVerification {}
|
||||
|
||||
impl rustls::ServerCertVerifier for NoCertificateVerification {
|
||||
fn verify_server_cert(&self,
|
||||
_roots: &rustls::RootCertStore,
|
||||
_presented_certs: &[rustls::Certificate],
|
||||
_dns_name: webpki::DNSNameRef<'_>,
|
||||
_ocsp: &[u8]) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
|
||||
Ok(rustls::ServerCertVerified::assertion())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_client(uri: &http::Uri, no_cert: bool) -> Result<CompactTxStreamerClient<Channel>, Box<dyn std::error::Error>> {
|
||||
let channel = if uri.scheme_str() == Some("http") {
|
||||
Channel::builder(uri.clone()).connect().await?
|
||||
} else {
|
||||
let mut config = ClientConfig::new();
|
||||
|
||||
config.alpn_protocols.push(b"h2".to_vec());
|
||||
config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
||||
config.root_store.add_pem_file(
|
||||
&mut PubCertificate::get("lightwalletd-lite.myhush.pem").unwrap().as_ref()).unwrap();
|
||||
|
||||
if no_cert {
|
||||
config.dangerous()
|
||||
.set_certificate_verifier(Arc::new(danger::NoCertificateVerification {}));
|
||||
}
|
||||
|
||||
let tls = ClientTlsConfig::new()
|
||||
.rustls_client_config(config)
|
||||
.domain_name(uri.host().unwrap());
|
||||
|
||||
Channel::builder(uri.clone())
|
||||
.tls_config(tls)
|
||||
.connect()
|
||||
.await?
|
||||
};
|
||||
|
||||
Ok(CompactTxStreamerClient::new(channel))
|
||||
}
|
||||
|
||||
// ==============
|
||||
// GRPC code
|
||||
// ==============
|
||||
async fn get_lightd_info(uri: &http::Uri, no_cert: bool) -> Result<LightdInfo, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(Empty {});
|
||||
|
||||
let response = client.get_lightd_info(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
pub fn get_info(uri: &http::Uri, no_cert: bool) -> Result<LightdInfo, String> {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
||||
|
||||
rt.block_on(get_lightd_info(uri, no_cert)).map_err( |e| e.to_string())
|
||||
}
|
||||
|
||||
|
||||
async fn get_coinsupply_info(uri: &http::Uri, no_cert: bool) -> Result<Coinsupply, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(Empty {});
|
||||
|
||||
let response = client.get_coinsupply(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
pub fn get_coinsupply(uri: http::Uri, no_cert: bool) -> Result<Coinsupply, String> {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
||||
|
||||
rt.block_on(get_coinsupply_info(&uri, no_cert)).map_err( |e| e.to_string())
|
||||
}
|
||||
|
||||
async fn get_block_range<F : 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
no_cert: bool,
|
||||
pool: ThreadPool,
|
||||
c: F
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where F : Fn(&[u8], u64) {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let bs = BlockId { height: start_height, hash: vec![] };
|
||||
let be = BlockId { height: end_height, hash: vec![] };
|
||||
|
||||
let request = Request::new(BlockRange { start: Some(bs), end: Some(be) });
|
||||
|
||||
let (tx, rx) = channel::<Option<CompactBlock>>();
|
||||
let (ftx, frx) = channel();
|
||||
|
||||
pool.execute(move || {
|
||||
while let Ok(Some(block)) = rx.recv() {
|
||||
use prost::Message;
|
||||
let mut encoded_buf = vec![];
|
||||
|
||||
if let Err(e) = block.encode(&mut encoded_buf) {
|
||||
error!("Error encoding block: {:?}", e);
|
||||
break;
|
||||
}
|
||||
|
||||
c(&encoded_buf, block.height);
|
||||
}
|
||||
|
||||
if let Err(e) = ftx.send(Ok(())) {
|
||||
error!("Error sending completion signal: {:?}", e);
|
||||
}
|
||||
});
|
||||
|
||||
let mut response = client.get_block_range(request).await?.into_inner();
|
||||
|
||||
while let Some(block) = response.message().await? {
|
||||
if let Err(e) = tx.send(Some(block)) {
|
||||
error!("Error sending block to channel: {:?}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = tx.send(None) {
|
||||
error!("Error sending end signal to channel: {:?}", e);
|
||||
}
|
||||
|
||||
frx.iter().take(1).collect::<Result<Vec<()>, String>>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn fetch_blocks<F : 'static + std::marker::Send>(uri: &http::Uri, start_height: u64, end_height: u64, no_cert: bool, pool: ThreadPool, c: F) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let es = format!("Error creating runtime {:?}", e);
|
||||
error!("{}", es);
|
||||
return Err(es);
|
||||
}
|
||||
};
|
||||
|
||||
match rt.block_on(get_block_range(uri, start_height, end_height, no_cert, pool, c)) {
|
||||
Ok(o) => Ok(o),
|
||||
Err(e) => {
|
||||
let e = format!("Error fetching blocks {:?}", e);
|
||||
error!("{}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get_address_txids GRPC call
|
||||
async fn get_address_txids<F : 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
address: String,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
no_cert: bool,
|
||||
c: F
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
let mut client = match get_client(uri, no_cert).await {
|
||||
Ok(client) => client,
|
||||
Err(e) => {
|
||||
error!("Error creating client: {:?}", e);
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
|
||||
let start = Some(BlockId{ height: start_height, hash: vec!()});
|
||||
let end = Some(BlockId{ height: end_height, hash: vec!()});
|
||||
|
||||
let request = Request::new(TransparentAddressBlockFilter{ address, range: Some(BlockRange{ start, end }) });
|
||||
|
||||
let maybe_response = match client.get_address_txids(request).await {
|
||||
Ok(response) => response,
|
||||
Err(e) => {
|
||||
error!("Error getting address txids: {:?}", e);
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
|
||||
let mut response = maybe_response.into_inner();
|
||||
|
||||
while let Some(tx) = response.message().await? {
|
||||
c(&tx.data, tx.height);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// function to monitor mempool transactions
|
||||
pub async fn monitor_mempool<F: 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
no_cert: bool,
|
||||
mut c: F
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
F: FnMut(RawTransaction) -> Result<(), Box<dyn std::error::Error>>,
|
||||
{
|
||||
|
||||
let mut client = get_client(uri, no_cert)
|
||||
.await
|
||||
.map_err(|e| format!("Error getting client: {:?}", e))?;
|
||||
|
||||
|
||||
let request = Request::new(Empty {});
|
||||
|
||||
let mut response = client
|
||||
.get_mempool_stream(request)
|
||||
.await
|
||||
.map_err(|e| format!("{}", e))?
|
||||
.into_inner();
|
||||
|
||||
|
||||
while let Ok(Some(rtx)) = response.message().await {
|
||||
|
||||
if let Err(e) = c(rtx) {
|
||||
info!("Error processing RawTransaction: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fetch_transparent_txids<F : 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
address: String,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
no_cert: bool,
|
||||
c: F
|
||||
) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let e = format!("Error creating runtime {:?}", e);
|
||||
error!("{}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
match rt.block_on(get_address_txids(uri, address.clone(), start_height, end_height, no_cert, c)) {
|
||||
Ok(o) => Ok(o),
|
||||
Err(e) => {
|
||||
let e = format!("Error with get_address_txids runtime {:?}", e);
|
||||
error!("{}", e);
|
||||
return Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get_transaction GRPC call
|
||||
async fn get_transaction(uri: &http::Uri, txid: TxId, no_cert: bool)
|
||||
-> Result<RawTransaction, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
let request = Request::new(TxFilter { block: None, index: 0, hash: txid.0.to_vec() });
|
||||
|
||||
let response = client.get_transaction(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
pub fn fetch_full_tx(uri: &http::Uri, txid: TxId, no_cert: bool) -> Result<Vec<u8>, String> {
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let errstr = format!("Error creating runtime {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
return Err(errstr);
|
||||
}
|
||||
};
|
||||
|
||||
match rt.block_on(get_transaction(uri, txid, no_cert)) {
|
||||
Ok(rawtx) => Ok(rawtx.data.to_vec()),
|
||||
Err(e) => {
|
||||
let errstr = format!("Error in get_transaction runtime {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
Err(errstr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send_transaction GRPC call
|
||||
async fn send_transaction(uri: &http::Uri, no_cert: bool, tx_bytes: Box<[u8]>) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(RawTransaction {data: tx_bytes.to_vec(), height: 0});
|
||||
|
||||
let response = client.send_transaction(request).await?;
|
||||
|
||||
let sendresponse = response.into_inner();
|
||||
if sendresponse.error_code == 0 {
|
||||
let mut txid = sendresponse.error_message;
|
||||
if txid.starts_with("\"") && txid.ends_with("\"") {
|
||||
txid = txid[1..txid.len()-1].to_string();
|
||||
}
|
||||
|
||||
Ok(txid)
|
||||
} else {
|
||||
Err(Box::from(format!("Error: {:?}", sendresponse)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn broadcast_raw_tx(uri: &http::Uri, no_cert: bool, tx_bytes: Box<[u8]>) -> Result<String, String> {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
||||
|
||||
rt.block_on(send_transaction(uri, no_cert, tx_bytes)).map_err( |e| e.to_string())
|
||||
}
|
||||
|
||||
// get_latest_block GRPC call
|
||||
async fn get_latest_block(uri: &http::Uri, no_cert: bool) -> Result<BlockId, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(ChainSpec {});
|
||||
|
||||
let response = client.get_latest_block(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
pub fn fetch_latest_block(uri: &http::Uri, no_cert: bool) -> Result<BlockId, String> {
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let errstr = format!("Error creating runtime {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
return Err(errstr);
|
||||
}
|
||||
};
|
||||
|
||||
rt.block_on(get_latest_block(uri, no_cert)).map_err(|e| {
|
||||
let errstr = format!("Error getting latest block {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
errstr
|
||||
})
|
||||
}
|
||||
// Copyright The Hush Developers 2019-2022
|
||||
// Released under the GPLv3
|
||||
use log::{info,error};
|
||||
use std::sync::Arc;
|
||||
use zcash_primitives::transaction::{TxId};
|
||||
|
||||
use crate::grpc_client::{ChainSpec, BlockId, BlockRange, RawTransaction, CompactBlock,
|
||||
TransparentAddressBlockFilter, TxFilter, Empty, LightdInfo, Coinsupply};
|
||||
use tonic::transport::{Channel, ClientTlsConfig};
|
||||
use tokio_rustls::{rustls::ClientConfig};
|
||||
use tonic::{Request};
|
||||
|
||||
use threadpool::ThreadPool;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use crate::PubCertificate;
|
||||
use crate::grpc_client::compact_tx_streamer_client::CompactTxStreamerClient;
|
||||
|
||||
mod danger {
|
||||
use tokio_rustls::rustls;
|
||||
use webpki;
|
||||
|
||||
pub struct NoCertificateVerification {}
|
||||
|
||||
impl rustls::ServerCertVerifier for NoCertificateVerification {
|
||||
fn verify_server_cert(&self,
|
||||
_roots: &rustls::RootCertStore,
|
||||
_presented_certs: &[rustls::Certificate],
|
||||
_dns_name: webpki::DNSNameRef<'_>,
|
||||
_ocsp: &[u8]) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
|
||||
Ok(rustls::ServerCertVerified::assertion())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_client(uri: &http::Uri, no_cert: bool) -> Result<CompactTxStreamerClient<Channel>, Box<dyn std::error::Error>> {
|
||||
let channel = if uri.scheme_str() == Some("http") {
|
||||
Channel::builder(uri.clone()).connect().await?
|
||||
} else {
|
||||
let mut config = ClientConfig::new();
|
||||
|
||||
config.alpn_protocols.push(b"h2".to_vec());
|
||||
config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
||||
config.root_store.add_pem_file(
|
||||
&mut PubCertificate::get("lightwalletd-lite.myhush.pem").unwrap().as_ref()).unwrap();
|
||||
|
||||
if no_cert {
|
||||
config.dangerous()
|
||||
.set_certificate_verifier(Arc::new(danger::NoCertificateVerification {}));
|
||||
}
|
||||
|
||||
let tls = ClientTlsConfig::new()
|
||||
.rustls_client_config(config)
|
||||
.domain_name(uri.host().unwrap());
|
||||
|
||||
Channel::builder(uri.clone())
|
||||
.tls_config(tls)
|
||||
.connect()
|
||||
.await?
|
||||
};
|
||||
|
||||
Ok(CompactTxStreamerClient::new(channel))
|
||||
}
|
||||
|
||||
// ==============
|
||||
// GRPC code
|
||||
// ==============
|
||||
async fn get_lightd_info(uri: &http::Uri, no_cert: bool) -> Result<LightdInfo, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(Empty {});
|
||||
|
||||
let response = client.get_lightd_info(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
pub fn get_info(uri: &http::Uri, no_cert: bool) -> Result<LightdInfo, String> {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
||||
|
||||
rt.block_on(get_lightd_info(uri, no_cert)).map_err( |e| e.to_string())
|
||||
}
|
||||
|
||||
|
||||
async fn get_coinsupply_info(uri: &http::Uri, no_cert: bool) -> Result<Coinsupply, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(Empty {});
|
||||
|
||||
let response = client.get_coinsupply(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
pub fn get_coinsupply(uri: http::Uri, no_cert: bool) -> Result<Coinsupply, String> {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
||||
|
||||
rt.block_on(get_coinsupply_info(&uri, no_cert)).map_err( |e| e.to_string())
|
||||
}
|
||||
|
||||
async fn get_block_range<F : 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
no_cert: bool,
|
||||
pool: ThreadPool,
|
||||
c: F
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where F : Fn(&[u8], u64) {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let bs = BlockId { height: start_height, hash: vec![] };
|
||||
let be = BlockId { height: end_height, hash: vec![] };
|
||||
|
||||
let request = Request::new(BlockRange { start: Some(bs), end: Some(be) });
|
||||
|
||||
let (tx, rx) = channel::<Option<CompactBlock>>();
|
||||
let (ftx, frx) = channel();
|
||||
|
||||
pool.execute(move || {
|
||||
while let Ok(Some(block)) = rx.recv() {
|
||||
use prost::Message;
|
||||
let mut encoded_buf = vec![];
|
||||
|
||||
if let Err(e) = block.encode(&mut encoded_buf) {
|
||||
error!("Error encoding block: {:?}", e);
|
||||
break;
|
||||
}
|
||||
|
||||
c(&encoded_buf, block.height);
|
||||
}
|
||||
|
||||
if let Err(e) = ftx.send(Ok(())) {
|
||||
error!("Error sending completion signal: {:?}", e);
|
||||
}
|
||||
});
|
||||
|
||||
let mut response = client.get_block_range(request).await?.into_inner();
|
||||
|
||||
while let Some(block) = response.message().await? {
|
||||
if let Err(e) = tx.send(Some(block)) {
|
||||
error!("Error sending block to channel: {:?}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = tx.send(None) {
|
||||
error!("Error sending end signal to channel: {:?}", e);
|
||||
}
|
||||
|
||||
frx.iter().take(1).collect::<Result<Vec<()>, String>>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn fetch_blocks<F : 'static + std::marker::Send>(uri: &http::Uri, start_height: u64, end_height: u64, no_cert: bool, pool: ThreadPool, c: F) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| format!("Error creating runtime {:?}", e))?;
|
||||
fetch_blocks_with_runtime(&mut rt, uri, start_height, end_height, no_cert, pool, c)
|
||||
}
|
||||
|
||||
pub fn fetch_blocks_with_runtime<F : 'static + std::marker::Send>(rt: &mut tokio::runtime::Runtime, uri: &http::Uri, start_height: u64, end_height: u64, no_cert: bool, pool: ThreadPool, c: F) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
match rt.block_on(get_block_range(uri, start_height, end_height, no_cert, pool, c)) {
|
||||
Ok(o) => Ok(o),
|
||||
Err(e) => {
|
||||
let e = format!("Error fetching blocks {:?}", e);
|
||||
error!("{}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get_address_txids GRPC call
|
||||
async fn get_address_txids<F : 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
address: String,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
no_cert: bool,
|
||||
c: F
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
let mut client = match get_client(uri, no_cert).await {
|
||||
Ok(client) => client,
|
||||
Err(e) => {
|
||||
error!("Error creating client: {:?}", e);
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
|
||||
let start = Some(BlockId{ height: start_height, hash: vec!()});
|
||||
let end = Some(BlockId{ height: end_height, hash: vec!()});
|
||||
|
||||
let request = Request::new(TransparentAddressBlockFilter{ address, range: Some(BlockRange{ start, end }) });
|
||||
|
||||
let maybe_response = match client.get_address_txids(request).await {
|
||||
Ok(response) => response,
|
||||
Err(e) => {
|
||||
error!("Error getting address txids: {:?}", e);
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
|
||||
let mut response = maybe_response.into_inner();
|
||||
|
||||
while let Some(tx) = response.message().await? {
|
||||
c(&tx.data, tx.height);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// function to monitor mempool transactions
|
||||
pub async fn monitor_mempool<F: 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
no_cert: bool,
|
||||
mut c: F
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
F: FnMut(RawTransaction) -> Result<(), Box<dyn std::error::Error>>,
|
||||
{
|
||||
|
||||
let mut client = get_client(uri, no_cert)
|
||||
.await
|
||||
.map_err(|e| format!("Error getting client: {:?}", e))?;
|
||||
|
||||
|
||||
let request = Request::new(Empty {});
|
||||
|
||||
let mut response = client
|
||||
.get_mempool_stream(request)
|
||||
.await
|
||||
.map_err(|e| format!("{}", e))?
|
||||
.into_inner();
|
||||
|
||||
|
||||
while let Ok(Some(rtx)) = response.message().await {
|
||||
|
||||
if let Err(e) = c(rtx) {
|
||||
info!("Error processing RawTransaction: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fetch_transparent_txids<F : 'static + std::marker::Send>(
|
||||
uri: &http::Uri,
|
||||
address: String,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
no_cert: bool,
|
||||
c: F
|
||||
) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let e = format!("Error creating runtime {:?}", e);
|
||||
error!("{}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
match rt.block_on(get_address_txids(uri, address.clone(), start_height, end_height, no_cert, c)) {
|
||||
Ok(o) => Ok(o),
|
||||
Err(e) => {
|
||||
let e = format!("Error with get_address_txids runtime {:?}", e);
|
||||
error!("{}", e);
|
||||
return Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get_transaction GRPC call
|
||||
async fn get_transaction(uri: &http::Uri, txid: TxId, no_cert: bool)
|
||||
-> Result<RawTransaction, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
let request = Request::new(TxFilter { block: None, index: 0, hash: txid.0.to_vec() });
|
||||
|
||||
let response = client.get_transaction(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
pub fn fetch_full_tx(uri: &http::Uri, txid: TxId, no_cert: bool) -> Result<Vec<u8>, String> {
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let errstr = format!("Error creating runtime {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
return Err(errstr);
|
||||
}
|
||||
};
|
||||
|
||||
match rt.block_on(get_transaction(uri, txid, no_cert)) {
|
||||
Ok(rawtx) => Ok(rawtx.data.to_vec()),
|
||||
Err(e) => {
|
||||
let errstr = format!("Error in get_transaction runtime {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
Err(errstr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send_transaction GRPC call
|
||||
async fn send_transaction(uri: &http::Uri, no_cert: bool, tx_bytes: Box<[u8]>) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(RawTransaction {data: tx_bytes.to_vec(), height: 0});
|
||||
|
||||
let response = client.send_transaction(request).await?;
|
||||
|
||||
let sendresponse = response.into_inner();
|
||||
if sendresponse.error_code == 0 {
|
||||
let mut txid = sendresponse.error_message;
|
||||
if txid.starts_with("\"") && txid.ends_with("\"") {
|
||||
txid = txid[1..txid.len()-1].to_string();
|
||||
}
|
||||
|
||||
Ok(txid)
|
||||
} else {
|
||||
Err(Box::from(format!("Error: {:?}", sendresponse)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn broadcast_raw_tx(uri: &http::Uri, no_cert: bool, tx_bytes: Box<[u8]>) -> Result<String, String> {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
||||
|
||||
rt.block_on(send_transaction(uri, no_cert, tx_bytes)).map_err( |e| e.to_string())
|
||||
}
|
||||
|
||||
// get_latest_block GRPC call
|
||||
async fn get_latest_block(uri: &http::Uri, no_cert: bool) -> Result<BlockId, Box<dyn std::error::Error>> {
|
||||
let mut client = get_client(uri, no_cert).await?;
|
||||
|
||||
let request = Request::new(ChainSpec {});
|
||||
|
||||
let response = client.get_latest_block(request).await?;
|
||||
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
pub fn fetch_latest_block(uri: &http::Uri, no_cert: bool) -> Result<BlockId, String> {
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let errstr = format!("Error creating runtime {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
return Err(errstr);
|
||||
}
|
||||
};
|
||||
|
||||
rt.block_on(get_latest_block(uri, no_cert)).map_err(|e| {
|
||||
let errstr = format!("Error getting latest block {}", e.to_string());
|
||||
error!("{}", errstr);
|
||||
errstr
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// Copyright The Hush Developers 2019-2022
|
||||
// Released under the GPLv3
|
||||
#[macro_use]
|
||||
extern crate rust_embed;
|
||||
|
||||
pub mod lightclient;
|
||||
pub mod grpcconnector;
|
||||
pub mod lightwallet;
|
||||
pub mod commands;
|
||||
|
||||
#[cfg(feature = "embed_params")]
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "zcash-params/"]
|
||||
pub struct SaplingParams;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "res/"]
|
||||
pub struct PubCertificate;
|
||||
|
||||
|
||||
pub const ANCHOR_OFFSET: u32 = 0;
|
||||
|
||||
pub mod grpc_client {
|
||||
tonic::include_proto!("cash.z.wallet.sdk.rpc");
|
||||
}
|
||||
// Copyright The Hush Developers 2019-2022
|
||||
// Released under the GPLv3
|
||||
#[macro_use]
|
||||
extern crate rust_embed;
|
||||
|
||||
pub mod lightclient;
|
||||
pub mod grpcconnector;
|
||||
pub mod lightwallet;
|
||||
pub mod commands;
|
||||
|
||||
#[cfg(feature = "embed_params")]
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "zcash-params/"]
|
||||
pub struct SaplingParams;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "res/"]
|
||||
pub struct PubCertificate;
|
||||
|
||||
|
||||
pub const ANCHOR_OFFSET: u32 = 0;
|
||||
|
||||
pub mod grpc_client {
|
||||
tonic::include_proto!("cash.z.wallet.sdk.rpc");
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,46 +1,46 @@
|
||||
//! Structs for handling supported address types.
|
||||
|
||||
use pairing::bls12_381::Bls12;
|
||||
use zcash_primitives::primitives::PaymentAddress;
|
||||
use zcash_client_backend::encoding::{decode_payment_address, decode_transparent_address};
|
||||
use zcash_primitives::legacy::TransparentAddress;
|
||||
|
||||
/// An address that funds can be sent to.
|
||||
pub enum RecipientAddress {
|
||||
Shielded(PaymentAddress<Bls12>),
|
||||
Transparent(TransparentAddress),
|
||||
}
|
||||
|
||||
impl From<PaymentAddress<Bls12>> for RecipientAddress {
|
||||
fn from(addr: PaymentAddress<Bls12>) -> Self {
|
||||
RecipientAddress::Shielded(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransparentAddress> for RecipientAddress {
|
||||
fn from(addr: TransparentAddress) -> Self {
|
||||
RecipientAddress::Transparent(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecipientAddress {
|
||||
pub fn from_str(s: &str, hrp_sapling_address: &str, b58_pubkey_address: [u8; 1], b58_script_address: [u8; 1]) -> Option<Self> {
|
||||
// Try to match a sapling z address
|
||||
if let Some(pa) = match decode_payment_address(hrp_sapling_address, s) {
|
||||
Ok(ret) => ret,
|
||||
Err(_) => None
|
||||
}
|
||||
{
|
||||
Some(RecipientAddress::Shielded(pa)) // Matched a shielded address
|
||||
} else if let Some(addr) = match decode_transparent_address(
|
||||
&b58_pubkey_address, &b58_script_address, s) {
|
||||
Ok(ret) => ret,
|
||||
Err(_) => None
|
||||
}
|
||||
{
|
||||
Some(RecipientAddress::Transparent(addr)) // Matched a transparent address
|
||||
} else {
|
||||
None // Didn't match anything
|
||||
}
|
||||
}
|
||||
}
|
||||
//! Structs for handling supported address types.
|
||||
|
||||
use pairing::bls12_381::Bls12;
|
||||
use zcash_primitives::primitives::PaymentAddress;
|
||||
use zcash_client_backend::encoding::{decode_payment_address, decode_transparent_address};
|
||||
use zcash_primitives::legacy::TransparentAddress;
|
||||
|
||||
/// An address that funds can be sent to.
|
||||
pub enum RecipientAddress {
|
||||
Shielded(PaymentAddress<Bls12>),
|
||||
Transparent(TransparentAddress),
|
||||
}
|
||||
|
||||
impl From<PaymentAddress<Bls12>> for RecipientAddress {
|
||||
fn from(addr: PaymentAddress<Bls12>) -> Self {
|
||||
RecipientAddress::Shielded(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransparentAddress> for RecipientAddress {
|
||||
fn from(addr: TransparentAddress) -> Self {
|
||||
RecipientAddress::Transparent(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecipientAddress {
|
||||
pub fn from_str(s: &str, hrp_sapling_address: &str, b58_pubkey_address: [u8; 1], b58_script_address: [u8; 1]) -> Option<Self> {
|
||||
// Try to match a sapling z address
|
||||
if let Some(pa) = match decode_payment_address(hrp_sapling_address, s) {
|
||||
Ok(ret) => ret,
|
||||
Err(_) => None
|
||||
}
|
||||
{
|
||||
Some(RecipientAddress::Shielded(pa)) // Matched a shielded address
|
||||
} else if let Some(addr) = match decode_transparent_address(
|
||||
&b58_pubkey_address, &b58_script_address, s) {
|
||||
Ok(ret) => ret,
|
||||
Err(_) => None
|
||||
}
|
||||
{
|
||||
Some(RecipientAddress::Transparent(addr)) // Matched a transparent address
|
||||
} else {
|
||||
None // Didn't match anything
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +1,126 @@
|
||||
use ring::{
|
||||
hmac::{self, Context, Key},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use secp256k1::{PublicKey, Secp256k1, SecretKey, SignOnly, VerifyOnly, Error};
|
||||
|
||||
lazy_static! {
|
||||
static ref SECP256K1_SIGN_ONLY: Secp256k1<SignOnly> = Secp256k1::signing_only();
|
||||
static ref SECP256K1_VERIFY_ONLY: Secp256k1<VerifyOnly> = Secp256k1::verification_only();
|
||||
}
|
||||
/// Random entropy, part of extended key.
|
||||
type ChainCode = Vec<u8>;
|
||||
|
||||
|
||||
const HARDENED_KEY_START_INDEX: u32 = 2_147_483_648; // 2 ** 31
|
||||
|
||||
/// KeyIndex indicates the key type and index of a child key.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum KeyIndex {
|
||||
/// Normal key, index range is from 0 to 2 ** 31 - 1
|
||||
Normal(u32),
|
||||
/// Hardened key, index range is from 2 ** 31 to 2 ** 32 - 1
|
||||
Hardened(u32),
|
||||
}
|
||||
|
||||
impl KeyIndex {
|
||||
|
||||
/// Check index range.
|
||||
pub fn is_valid(self) -> bool {
|
||||
match self {
|
||||
KeyIndex::Normal(i) => i < HARDENED_KEY_START_INDEX,
|
||||
KeyIndex::Hardened(i) => i >= HARDENED_KEY_START_INDEX,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate Hardened KeyIndex from normalize index value.
|
||||
pub fn hardened_from_normalize_index(i: u32) -> Result<KeyIndex, Error> {
|
||||
if i < HARDENED_KEY_START_INDEX {
|
||||
Ok(KeyIndex::Hardened(HARDENED_KEY_START_INDEX + i))
|
||||
} else {
|
||||
Ok(KeyIndex::Hardened(i))
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate KeyIndex from raw index value.
|
||||
pub fn from_index(i: u32) -> Result<Self, Error> {
|
||||
if i < HARDENED_KEY_START_INDEX {
|
||||
Ok(KeyIndex::Normal(i))
|
||||
} else {
|
||||
Ok(KeyIndex::Hardened(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for KeyIndex {
|
||||
fn from(index: u32) -> Self {
|
||||
KeyIndex::from_index(index).expect("KeyIndex")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// ExtendedPrivKey is used for child key derivation.
|
||||
/// See [secp256k1 crate documentation](https://docs.rs/secp256k1) for SecretKey signatures usage.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ExtendedPrivKey {
|
||||
pub private_key: SecretKey,
|
||||
pub chain_code: ChainCode,
|
||||
}
|
||||
|
||||
|
||||
impl ExtendedPrivKey {
|
||||
|
||||
/// Generate an ExtendedPrivKey from seed
|
||||
pub fn with_seed(seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
|
||||
let signature = {
|
||||
let signing_key = Key::new(hmac::HMAC_SHA512, b"Bitcoin seed");
|
||||
let mut h = Context::with_key(&signing_key);
|
||||
h.update(&seed);
|
||||
h.sign()
|
||||
};
|
||||
let sig_bytes = signature.as_ref();
|
||||
let (key, chain_code) = sig_bytes.split_at(sig_bytes.len() / 2);
|
||||
let private_key = SecretKey::from_slice(key)?;
|
||||
Ok(ExtendedPrivKey {
|
||||
private_key,
|
||||
chain_code: chain_code.to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
fn sign_hardended_key(&self, index: u32) -> ring::hmac::Tag {
|
||||
let signing_key = Key::new(hmac::HMAC_SHA512, &self.chain_code);
|
||||
let mut h = Context::with_key(&signing_key);
|
||||
h.update(&[0x00]);
|
||||
h.update(&self.private_key[..]);
|
||||
h.update(&index.to_be_bytes());
|
||||
h.sign()
|
||||
}
|
||||
|
||||
fn sign_normal_key(&self, index: u32) -> ring::hmac::Tag {
|
||||
let signing_key = Key::new(hmac::HMAC_SHA512, &self.chain_code);
|
||||
let mut h = Context::with_key(&signing_key);
|
||||
let public_key = PublicKey::from_secret_key(&SECP256K1_SIGN_ONLY, &self.private_key);
|
||||
h.update(&public_key.serialize());
|
||||
h.update(&index.to_be_bytes());
|
||||
h.sign()
|
||||
}
|
||||
|
||||
/// Derive a child key from ExtendedPrivKey.
|
||||
pub fn derive_private_key(&self, key_index: KeyIndex) -> Result<ExtendedPrivKey, Error> {
|
||||
if !key_index.is_valid() {
|
||||
return Err(Error::InvalidTweak);
|
||||
}
|
||||
let signature = match key_index {
|
||||
KeyIndex::Hardened(index) => self.sign_hardended_key(index),
|
||||
KeyIndex::Normal(index) => self.sign_normal_key(index),
|
||||
};
|
||||
let sig_bytes = signature.as_ref();
|
||||
let (key, chain_code) = sig_bytes.split_at(sig_bytes.len() / 2);
|
||||
let mut private_key = SecretKey::from_slice(key)?;
|
||||
private_key.add_assign(&self.private_key[..])?;
|
||||
Ok(ExtendedPrivKey {
|
||||
private_key,
|
||||
chain_code: chain_code.to_vec(),
|
||||
})
|
||||
}
|
||||
}
|
||||
use ring::{
|
||||
hmac::{self, Context, Key},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use secp256k1::{PublicKey, Secp256k1, SecretKey, SignOnly, VerifyOnly, Error};
|
||||
|
||||
lazy_static! {
|
||||
static ref SECP256K1_SIGN_ONLY: Secp256k1<SignOnly> = Secp256k1::signing_only();
|
||||
static ref SECP256K1_VERIFY_ONLY: Secp256k1<VerifyOnly> = Secp256k1::verification_only();
|
||||
}
|
||||
/// Random entropy, part of extended key.
|
||||
type ChainCode = Vec<u8>;
|
||||
|
||||
|
||||
const HARDENED_KEY_START_INDEX: u32 = 2_147_483_648; // 2 ** 31
|
||||
|
||||
/// KeyIndex indicates the key type and index of a child key.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum KeyIndex {
|
||||
/// Normal key, index range is from 0 to 2 ** 31 - 1
|
||||
Normal(u32),
|
||||
/// Hardened key, index range is from 2 ** 31 to 2 ** 32 - 1
|
||||
Hardened(u32),
|
||||
}
|
||||
|
||||
impl KeyIndex {
|
||||
|
||||
/// Check index range.
|
||||
pub fn is_valid(self) -> bool {
|
||||
match self {
|
||||
KeyIndex::Normal(i) => i < HARDENED_KEY_START_INDEX,
|
||||
KeyIndex::Hardened(i) => i >= HARDENED_KEY_START_INDEX,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate Hardened KeyIndex from normalize index value.
|
||||
pub fn hardened_from_normalize_index(i: u32) -> Result<KeyIndex, Error> {
|
||||
if i < HARDENED_KEY_START_INDEX {
|
||||
Ok(KeyIndex::Hardened(HARDENED_KEY_START_INDEX + i))
|
||||
} else {
|
||||
Ok(KeyIndex::Hardened(i))
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate KeyIndex from raw index value.
|
||||
pub fn from_index(i: u32) -> Result<Self, Error> {
|
||||
if i < HARDENED_KEY_START_INDEX {
|
||||
Ok(KeyIndex::Normal(i))
|
||||
} else {
|
||||
Ok(KeyIndex::Hardened(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for KeyIndex {
|
||||
fn from(index: u32) -> Self {
|
||||
KeyIndex::from_index(index).expect("KeyIndex")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// ExtendedPrivKey is used for child key derivation.
|
||||
/// See [secp256k1 crate documentation](https://docs.rs/secp256k1) for SecretKey signatures usage.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ExtendedPrivKey {
|
||||
pub private_key: SecretKey,
|
||||
pub chain_code: ChainCode,
|
||||
}
|
||||
|
||||
|
||||
impl ExtendedPrivKey {
|
||||
|
||||
/// Generate an ExtendedPrivKey from seed
|
||||
pub fn with_seed(seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
|
||||
let signature = {
|
||||
let signing_key = Key::new(hmac::HMAC_SHA512, b"Bitcoin seed");
|
||||
let mut h = Context::with_key(&signing_key);
|
||||
h.update(&seed);
|
||||
h.sign()
|
||||
};
|
||||
let sig_bytes = signature.as_ref();
|
||||
let (key, chain_code) = sig_bytes.split_at(sig_bytes.len() / 2);
|
||||
let private_key = SecretKey::from_slice(key)?;
|
||||
Ok(ExtendedPrivKey {
|
||||
private_key,
|
||||
chain_code: chain_code.to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
fn sign_hardended_key(&self, index: u32) -> ring::hmac::Tag {
|
||||
let signing_key = Key::new(hmac::HMAC_SHA512, &self.chain_code);
|
||||
let mut h = Context::with_key(&signing_key);
|
||||
h.update(&[0x00]);
|
||||
h.update(&self.private_key[..]);
|
||||
h.update(&index.to_be_bytes());
|
||||
h.sign()
|
||||
}
|
||||
|
||||
fn sign_normal_key(&self, index: u32) -> ring::hmac::Tag {
|
||||
let signing_key = Key::new(hmac::HMAC_SHA512, &self.chain_code);
|
||||
let mut h = Context::with_key(&signing_key);
|
||||
let public_key = PublicKey::from_secret_key(&SECP256K1_SIGN_ONLY, &self.private_key);
|
||||
h.update(&public_key.serialize());
|
||||
h.update(&index.to_be_bytes());
|
||||
h.sign()
|
||||
}
|
||||
|
||||
/// Derive a child key from ExtendedPrivKey.
|
||||
pub fn derive_private_key(&self, key_index: KeyIndex) -> Result<ExtendedPrivKey, Error> {
|
||||
if !key_index.is_valid() {
|
||||
return Err(Error::InvalidTweak);
|
||||
}
|
||||
let signature = match key_index {
|
||||
KeyIndex::Hardened(index) => self.sign_hardended_key(index),
|
||||
KeyIndex::Normal(index) => self.sign_normal_key(index),
|
||||
};
|
||||
let sig_bytes = signature.as_ref();
|
||||
let (key, chain_code) = sig_bytes.split_at(sig_bytes.len() / 2);
|
||||
let mut private_key = SecretKey::from_slice(key)?;
|
||||
private_key.add_assign(&self.private_key[..])?;
|
||||
Ok(ExtendedPrivKey {
|
||||
private_key,
|
||||
chain_code: chain_code.to_vec(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,123 +1,123 @@
|
||||
//! Abstractions over the proving system and parameters for ease of use.
|
||||
|
||||
use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs::Fs, Unknown},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey},
|
||||
redjubjub::{PublicKey, Signature},
|
||||
transaction::components::Amount
|
||||
};
|
||||
use zcash_primitives::{
|
||||
merkle_tree::CommitmentTreeWitness, prover::TxProver, sapling::Node,
|
||||
transaction::components::GROTH_PROOF_SIZE, JUBJUB,
|
||||
};
|
||||
use zcash_proofs::sapling::SaplingProvingContext;
|
||||
|
||||
/// An implementation of [`TxProver`] using Sapling Spend and Output parameters provided
|
||||
/// in-memory.
|
||||
pub struct InMemTxProver {
|
||||
spend_params: Parameters<Bls12>,
|
||||
spend_vk: PreparedVerifyingKey<Bls12>,
|
||||
output_params: Parameters<Bls12>,
|
||||
}
|
||||
|
||||
impl InMemTxProver {
|
||||
pub fn new(spend_params: &[u8], output_params: &[u8]) -> Self {
|
||||
// Deserialize params
|
||||
let spend_params = Parameters::<Bls12>::read(spend_params, false)
|
||||
.expect("couldn't deserialize Sapling spend parameters file");
|
||||
let output_params = Parameters::<Bls12>::read(output_params, false)
|
||||
.expect("couldn't deserialize Sapling spend parameters file");
|
||||
|
||||
// Prepare verifying keys
|
||||
let spend_vk = prepare_verifying_key(&spend_params.vk);
|
||||
|
||||
InMemTxProver {
|
||||
spend_params,
|
||||
spend_vk,
|
||||
output_params,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TxProver for InMemTxProver {
|
||||
type SaplingProvingContext = SaplingProvingContext;
|
||||
|
||||
fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext {
|
||||
SaplingProvingContext::new()
|
||||
}
|
||||
|
||||
fn spend_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey<Bls12>,
|
||||
diversifier: Diversifier,
|
||||
rcm: Fs,
|
||||
ar: Fs,
|
||||
value: u64,
|
||||
anchor: Fr,
|
||||
witness: CommitmentTreeWitness<Node>,
|
||||
) -> Result<
|
||||
(
|
||||
[u8; GROTH_PROOF_SIZE],
|
||||
edwards::Point<Bls12, Unknown>,
|
||||
PublicKey<Bls12>,
|
||||
),
|
||||
(),
|
||||
> {
|
||||
let (proof, cv, rk) = ctx.spend_proof(
|
||||
proof_generation_key,
|
||||
diversifier,
|
||||
rcm,
|
||||
ar,
|
||||
value,
|
||||
anchor,
|
||||
witness,
|
||||
&self.spend_params,
|
||||
&self.spend_vk,
|
||||
&JUBJUB,
|
||||
)?;
|
||||
|
||||
let mut zkproof = [0u8; GROTH_PROOF_SIZE];
|
||||
proof
|
||||
.write(&mut zkproof[..])
|
||||
.expect("should be able to serialize a proof");
|
||||
|
||||
Ok((zkproof, cv, rk))
|
||||
}
|
||||
|
||||
fn output_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
esk: Fs,
|
||||
payment_address: PaymentAddress<Bls12>,
|
||||
rcm: Fs,
|
||||
value: u64,
|
||||
) -> ([u8; GROTH_PROOF_SIZE], edwards::Point<Bls12, Unknown>) {
|
||||
let (proof, cv) = ctx.output_proof(
|
||||
esk,
|
||||
payment_address,
|
||||
rcm,
|
||||
value,
|
||||
&self.output_params,
|
||||
&JUBJUB,
|
||||
);
|
||||
|
||||
let mut zkproof = [0u8; GROTH_PROOF_SIZE];
|
||||
proof
|
||||
.write(&mut zkproof[..])
|
||||
.expect("should be able to serialize a proof");
|
||||
|
||||
(zkproof, cv)
|
||||
}
|
||||
|
||||
fn binding_sig(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
value_balance: Amount,
|
||||
sighash: &[u8; 32],
|
||||
) -> Result<Signature, ()> {
|
||||
ctx.binding_sig(value_balance, sighash, &JUBJUB)
|
||||
}
|
||||
}
|
||||
//! Abstractions over the proving system and parameters for ease of use.
|
||||
|
||||
use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs::Fs, Unknown},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey},
|
||||
redjubjub::{PublicKey, Signature},
|
||||
transaction::components::Amount
|
||||
};
|
||||
use zcash_primitives::{
|
||||
merkle_tree::CommitmentTreeWitness, prover::TxProver, sapling::Node,
|
||||
transaction::components::GROTH_PROOF_SIZE, JUBJUB,
|
||||
};
|
||||
use zcash_proofs::sapling::SaplingProvingContext;
|
||||
|
||||
/// An implementation of [`TxProver`] using Sapling Spend and Output parameters provided
|
||||
/// in-memory.
|
||||
pub struct InMemTxProver {
|
||||
spend_params: Parameters<Bls12>,
|
||||
spend_vk: PreparedVerifyingKey<Bls12>,
|
||||
output_params: Parameters<Bls12>,
|
||||
}
|
||||
|
||||
impl InMemTxProver {
|
||||
pub fn new(spend_params: &[u8], output_params: &[u8]) -> Self {
|
||||
// Deserialize params
|
||||
let spend_params = Parameters::<Bls12>::read(spend_params, false)
|
||||
.expect("couldn't deserialize Sapling spend parameters file");
|
||||
let output_params = Parameters::<Bls12>::read(output_params, false)
|
||||
.expect("couldn't deserialize Sapling spend parameters file");
|
||||
|
||||
// Prepare verifying keys
|
||||
let spend_vk = prepare_verifying_key(&spend_params.vk);
|
||||
|
||||
InMemTxProver {
|
||||
spend_params,
|
||||
spend_vk,
|
||||
output_params,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TxProver for InMemTxProver {
|
||||
type SaplingProvingContext = SaplingProvingContext;
|
||||
|
||||
fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext {
|
||||
SaplingProvingContext::new()
|
||||
}
|
||||
|
||||
fn spend_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey<Bls12>,
|
||||
diversifier: Diversifier,
|
||||
rcm: Fs,
|
||||
ar: Fs,
|
||||
value: u64,
|
||||
anchor: Fr,
|
||||
witness: CommitmentTreeWitness<Node>,
|
||||
) -> Result<
|
||||
(
|
||||
[u8; GROTH_PROOF_SIZE],
|
||||
edwards::Point<Bls12, Unknown>,
|
||||
PublicKey<Bls12>,
|
||||
),
|
||||
(),
|
||||
> {
|
||||
let (proof, cv, rk) = ctx.spend_proof(
|
||||
proof_generation_key,
|
||||
diversifier,
|
||||
rcm,
|
||||
ar,
|
||||
value,
|
||||
anchor,
|
||||
witness,
|
||||
&self.spend_params,
|
||||
&self.spend_vk,
|
||||
&JUBJUB,
|
||||
)?;
|
||||
|
||||
let mut zkproof = [0u8; GROTH_PROOF_SIZE];
|
||||
proof
|
||||
.write(&mut zkproof[..])
|
||||
.expect("should be able to serialize a proof");
|
||||
|
||||
Ok((zkproof, cv, rk))
|
||||
}
|
||||
|
||||
fn output_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
esk: Fs,
|
||||
payment_address: PaymentAddress<Bls12>,
|
||||
rcm: Fs,
|
||||
value: u64,
|
||||
) -> ([u8; GROTH_PROOF_SIZE], edwards::Point<Bls12, Unknown>) {
|
||||
let (proof, cv) = ctx.output_proof(
|
||||
esk,
|
||||
payment_address,
|
||||
rcm,
|
||||
value,
|
||||
&self.output_params,
|
||||
&JUBJUB,
|
||||
);
|
||||
|
||||
let mut zkproof = [0u8; GROTH_PROOF_SIZE];
|
||||
proof
|
||||
.write(&mut zkproof[..])
|
||||
.expect("should be able to serialize a proof");
|
||||
|
||||
(zkproof, cv)
|
||||
}
|
||||
|
||||
fn binding_sig(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
value_balance: Amount,
|
||||
sighash: &[u8; 32],
|
||||
) -> Result<Signature, ()> {
|
||||
ctx.binding_sig(value_balance, sighash, &JUBJUB)
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,21 @@
|
||||
use std::io::{self, Read, Write};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
pub fn read_string<R: Read>(mut reader: R) -> io::Result<String> {
|
||||
// Strings are written as <littleendian> len + bytes
|
||||
let str_len = reader.read_u64::<LittleEndian>()?;
|
||||
let mut str_bytes = vec![0; str_len as usize];
|
||||
reader.read_exact(&mut str_bytes)?;
|
||||
|
||||
let str = String::from_utf8(str_bytes).map_err(|e| {
|
||||
io::Error::new(io::ErrorKind::InvalidData, e.to_string())
|
||||
})?;
|
||||
|
||||
Ok(str)
|
||||
}
|
||||
|
||||
pub fn write_string<W: Write>(mut writer: W, s: &String) -> io::Result<()> {
|
||||
// Strings are written as len + utf8
|
||||
writer.write_u64::<LittleEndian>(s.as_bytes().len() as u64)?;
|
||||
writer.write_all(s.as_bytes())
|
||||
use std::io::{self, Read, Write};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
pub fn read_string<R: Read>(mut reader: R) -> io::Result<String> {
|
||||
// Strings are written as <littleendian> len + bytes
|
||||
let str_len = reader.read_u64::<LittleEndian>()?;
|
||||
let mut str_bytes = vec![0; str_len as usize];
|
||||
reader.read_exact(&mut str_bytes)?;
|
||||
|
||||
let str = String::from_utf8(str_bytes).map_err(|e| {
|
||||
io::Error::new(io::ErrorKind::InvalidData, e.to_string())
|
||||
})?;
|
||||
|
||||
Ok(str)
|
||||
}
|
||||
|
||||
pub fn write_string<W: Write>(mut writer: W, s: &String) -> io::Result<()> {
|
||||
// Strings are written as len + utf8
|
||||
writer.write_u64::<LittleEndian>(s.as_bytes().len() as u64)?;
|
||||
writer.write_all(s.as_bytes())
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
222
mkrelease.sh
222
mkrelease.sh
@@ -1,111 +1,111 @@
|
||||
#!/bin/bash
|
||||
# This script depends on a docker image already being built
|
||||
# To build it,
|
||||
# cd docker
|
||||
# docker build --tag rustbuild:latest .
|
||||
|
||||
POSITIONAL=()
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-v|--version)
|
||||
APP_VERSION="$2"
|
||||
shift # past argument
|
||||
shift # past value
|
||||
;;
|
||||
*) # unknown option
|
||||
POSITIONAL+=("$1") # save it in an array for later
|
||||
shift # past argument
|
||||
;;
|
||||
esac
|
||||
done
|
||||
set -- "${POSITIONAL[@]}" # restore positional parameters
|
||||
|
||||
if [ -z $APP_VERSION ]; then echo "APP_VERSION is not set"; exit 1; fi
|
||||
|
||||
# Write the version file
|
||||
echo "pub const VERSION:&str = \"$APP_VERSION\";" > /cli/src/version.rs
|
||||
|
||||
# First, do the tests
|
||||
cd lib && cargo test --release
|
||||
retVal=$?
|
||||
if [ $retVal -ne 0 ]; then
|
||||
echo "Error"
|
||||
exit $retVal
|
||||
fi
|
||||
cd ..
|
||||
|
||||
# Compile for mac directly
|
||||
cargo build --release
|
||||
|
||||
#macOS
|
||||
rm -rf target/macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/release/silentdragonxlite-cli target/macOS-silentdragonxlite-cli-v$APP_VERSION/
|
||||
|
||||
# For Windows and Linux, build via docker
|
||||
docker run --rm -v $(pwd)/:/opt/silentdragonxlite-cli rustbuild:latest bash -c "cd /opt/silentdragonxlite-cli && cargo build --release && cargo build --release --target armv7-unknown-linux-gnueabihf && cargo build --release --target aarch64-unknown-linux-gnu && SODIUM_LIB_DIR='/opt/libsodium-win64/lib/' cargo build --release --target x86_64-pc-windows-gnu"
|
||||
|
||||
# Now sign and zip the binaries
|
||||
# macOS
|
||||
gpg --batch --output target/macOS-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/macOS-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r macOS-silentdragonxlite-cli-v$APP_VERSION.zip macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#Linux
|
||||
rm -rf target/linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/release/silentdragonxlite-cli target/linux-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/linux-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/linux-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r linux-silentdragonxlite-cli-v$APP_VERSION.zip linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#Windows
|
||||
rm -rf target/Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/x86_64-pc-windows-gnu/release/silentdragonxlite-cli.exe target/Windows-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/Windows-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/Windows-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.exe
|
||||
cd target
|
||||
cd Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli.exe > sha256sum.txt
|
||||
cd ..
|
||||
zip -r Windows-silentdragonxlite-cli-v$APP_VERSION.zip Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#Armv7
|
||||
rm -rf target/Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/armv7-unknown-linux-gnueabihf/release/silentdragonxlite-cli target/Armv7-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/Armv7-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/Armv7-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r Armv7-silentdragonxlite-cli-v$APP_VERSION.zip Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#AARCH64
|
||||
rm -rf target/aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/aarch64-unknown-linux-gnu/release/silentdragonxlite-cli target/aarch64-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/aarch64-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/aarch64-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r aarch64-silentdragonxlite-cli-v$APP_VERSION.zip aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
#!/bin/bash
|
||||
# This script depends on a docker image already being built
|
||||
# To build it,
|
||||
# cd docker
|
||||
# docker build --tag rustbuild:latest .
|
||||
|
||||
POSITIONAL=()
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-v|--version)
|
||||
APP_VERSION="$2"
|
||||
shift # past argument
|
||||
shift # past value
|
||||
;;
|
||||
*) # unknown option
|
||||
POSITIONAL+=("$1") # save it in an array for later
|
||||
shift # past argument
|
||||
;;
|
||||
esac
|
||||
done
|
||||
set -- "${POSITIONAL[@]}" # restore positional parameters
|
||||
|
||||
if [ -z $APP_VERSION ]; then echo "APP_VERSION is not set"; exit 1; fi
|
||||
|
||||
# Write the version file
|
||||
echo "pub const VERSION:&str = \"$APP_VERSION\";" > /cli/src/version.rs
|
||||
|
||||
# First, do the tests
|
||||
cd lib && cargo test --release
|
||||
retVal=$?
|
||||
if [ $retVal -ne 0 ]; then
|
||||
echo "Error"
|
||||
exit $retVal
|
||||
fi
|
||||
cd ..
|
||||
|
||||
# Compile for mac directly
|
||||
cargo build --release
|
||||
|
||||
#macOS
|
||||
rm -rf target/macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/release/silentdragonxlite-cli target/macOS-silentdragonxlite-cli-v$APP_VERSION/
|
||||
|
||||
# For Windows and Linux, build via docker
|
||||
docker run --rm -v $(pwd)/:/opt/silentdragonxlite-cli rustbuild:latest bash -c "cd /opt/silentdragonxlite-cli && cargo build --release && cargo build --release --target armv7-unknown-linux-gnueabihf && cargo build --release --target aarch64-unknown-linux-gnu && SODIUM_LIB_DIR='/opt/libsodium-win64/lib/' cargo build --release --target x86_64-pc-windows-gnu"
|
||||
|
||||
# Now sign and zip the binaries
|
||||
# macOS
|
||||
gpg --batch --output target/macOS-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/macOS-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r macOS-silentdragonxlite-cli-v$APP_VERSION.zip macOS-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#Linux
|
||||
rm -rf target/linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/release/silentdragonxlite-cli target/linux-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/linux-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/linux-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r linux-silentdragonxlite-cli-v$APP_VERSION.zip linux-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#Windows
|
||||
rm -rf target/Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/x86_64-pc-windows-gnu/release/silentdragonxlite-cli.exe target/Windows-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/Windows-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/Windows-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.exe
|
||||
cd target
|
||||
cd Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli.exe > sha256sum.txt
|
||||
cd ..
|
||||
zip -r Windows-silentdragonxlite-cli-v$APP_VERSION.zip Windows-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#Armv7
|
||||
rm -rf target/Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/armv7-unknown-linux-gnueabihf/release/silentdragonxlite-cli target/Armv7-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/Armv7-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/Armv7-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r Armv7-silentdragonxlite-cli-v$APP_VERSION.zip Armv7-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
|
||||
#AARCH64
|
||||
rm -rf target/aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
mkdir -p target/aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
cp target/aarch64-unknown-linux-gnu/release/silentdragonxlite-cli target/aarch64-silentdragonxlite-cli-v$APP_VERSION/
|
||||
gpg --batch --output target/aarch64-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli.sig --detach-sig target/aarch64-silentdragonxlite-cli-v$APP_VERSION/silentdragonxlite-cli
|
||||
cd target
|
||||
cd aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
gsha256sum silentdragonxlite-cli > sha256sum.txt
|
||||
cd ..
|
||||
zip -r aarch64-silentdragonxlite-cli-v$APP_VERSION.zip aarch64-silentdragonxlite-cli-v$APP_VERSION
|
||||
cd ..
|
||||
|
||||
100
util/build.sh
100
util/build.sh
@@ -1,50 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2021-2022 The Hush Developers
|
||||
# Distributed under the GPLv3 software license, see the accompanying
|
||||
# file LICENSE or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
|
||||
# Purpose: Script to build Hush silentdragonxlite on x86 64-bit arch
|
||||
## Usage: ./util/build.sh
|
||||
|
||||
# Check if rustc is installed on system and exits if it is not
|
||||
if ! [ -x "$(command -v rustc)" ]; then
|
||||
echo 'Error: rustc is not installed. Install it and try again.' >&2
|
||||
exit 1
|
||||
fi
|
||||
# Check if cargo is installed on system and exits if it is not
|
||||
if ! [ -x "$(command -v cargo)" ]; then
|
||||
echo 'Error: cargo is not installed. Install it and try again.' >&2
|
||||
exit 1
|
||||
fi
|
||||
# Check if rustfmt is installed on system and exits if it is not
|
||||
if ! [ -x "$(command -v rustfmt)" ]; then
|
||||
echo 'Error: rustfmt is not installed. Install it and try again.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Welcome to the Hush magic folks..."
|
||||
echo ""
|
||||
echo " #### ##### # #### # # ##### # # # # ##### ##### # # # ###### "
|
||||
echo "# # # # # # # # # # # # # # # # # # ## ## # "
|
||||
echo " #### # # # ##### # # # ##### # # # # # # # # # ## # ##### "
|
||||
echo " # # # # # # # # # # # # # # # # # # # # "
|
||||
echo "# # # # # # # # # # # # # # # # # # # # # # "
|
||||
echo " #### ##### ###### #### ###### # ##### #### # ###### ##### # # # # ###### "
|
||||
|
||||
# now to compiling...
|
||||
echo ""
|
||||
echo "You have the requirements installed, so let's build!"
|
||||
|
||||
cargo build --release
|
||||
|
||||
# check if compile was success
|
||||
if [ $? -ne 0 ]; then
|
||||
echo ""
|
||||
echo 'Error: Something went wrong and it did not build successfully... Please reach out if you need support.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Hush silentdragonxlite-cli is now compiled for you. Enjoy and reach out if you need support."
|
||||
echo "For options, run ./silentdragonxlite --help"
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2021-2022 The Hush Developers
|
||||
# Distributed under the GPLv3 software license, see the accompanying
|
||||
# file LICENSE or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
|
||||
# Purpose: Script to build Hush silentdragonxlite on x86 64-bit arch
|
||||
## Usage: ./util/build.sh
|
||||
|
||||
# Check if rustc is installed on system and exits if it is not
|
||||
if ! [ -x "$(command -v rustc)" ]; then
|
||||
echo 'Error: rustc is not installed. Install it and try again.' >&2
|
||||
exit 1
|
||||
fi
|
||||
# Check if cargo is installed on system and exits if it is not
|
||||
if ! [ -x "$(command -v cargo)" ]; then
|
||||
echo 'Error: cargo is not installed. Install it and try again.' >&2
|
||||
exit 1
|
||||
fi
|
||||
# Check if rustfmt is installed on system and exits if it is not
|
||||
if ! [ -x "$(command -v rustfmt)" ]; then
|
||||
echo 'Error: rustfmt is not installed. Install it and try again.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Welcome to the Hush magic folks..."
|
||||
echo ""
|
||||
echo " #### ##### # #### # # ##### # # # # ##### ##### # # # ###### "
|
||||
echo "# # # # # # # # # # # # # # # # # # ## ## # "
|
||||
echo " #### # # # ##### # # # ##### # # # # # # # # # ## # ##### "
|
||||
echo " # # # # # # # # # # # # # # # # # # # # "
|
||||
echo "# # # # # # # # # # # # # # # # # # # # # # "
|
||||
echo " #### ##### ###### #### ###### # ##### #### # ###### ##### # # # # ###### "
|
||||
|
||||
# now to compiling...
|
||||
echo ""
|
||||
echo "You have the requirements installed, so let's build!"
|
||||
|
||||
cargo build --release
|
||||
|
||||
# check if compile was success
|
||||
if [ $? -ne 0 ]; then
|
||||
echo ""
|
||||
echo 'Error: Something went wrong and it did not build successfully... Please reach out if you need support.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Hush silentdragonxlite-cli is now compiled for you. Enjoy and reach out if you need support."
|
||||
echo "For options, run ./silentdragonxlite --help"
|
||||
|
||||
Reference in New Issue
Block a user