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