├── .github └── workflows │ ├── ci.yaml │ └── deploy.yaml ├── .gitignore ├── .rustfmt.toml ├── Cargo.toml ├── LICENSE-APACHE ├── README.md ├── build.rs ├── hive-os ├── h-config.sh ├── h-manifest.conf ├── h-run.sh └── h-stats.sh ├── mmpos ├── mmp-external.conf └── mmp-stats.sh ├── proto ├── messages.proto ├── p2p.proto └── rpc.proto └── src ├── asm ├── keccakf1600_x86-64-elf.s ├── keccakf1600_x86-64-mingw64.s ├── keccakf1600_x86-64-msvc.asm ├── keccakf1600_x86-64-osx.s └── keccakf1600_x86-64-win64.s ├── cli.rs ├── client.rs ├── main.rs ├── miner.rs ├── pow.rs ├── pow ├── hasher.rs ├── heavy_hash.rs ├── keccak.rs └── xoshiro.rs ├── spectred_messages.rs ├── swap_rust.rs └── target.rs /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [push, pull_request] 3 | 4 | env: 5 | CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse # Should improve the speed of the build and the cache size. 6 | ZSTD_CLEVEL: 10 # We want some tradeoff between speed and size. 7 | ZSTD_NBTHREADS: 2 # We only got 2 cores. 8 | 9 | jobs: 10 | check: 11 | name: Check 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout sources 15 | uses: actions/checkout@v4 16 | 17 | - name: Install toolchain 18 | id: rust-toolchain 19 | uses: dtolnay/rust-toolchain@stable 20 | 21 | - name: Cache cargo registry 22 | uses: actions/cache@v4 23 | with: 24 | path: ~/.cargo/registry 25 | key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} 26 | restore-keys: | 27 | ${{ runner.os }}-cargo-registry- 28 | 29 | - name: Cache cargo index 30 | uses: actions/cache@v4 31 | with: 32 | path: ~/.cargo/git 33 | key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} 34 | restore-keys: | 35 | ${{ runner.os }}-cargo-git- 36 | 37 | - name: Cache build 38 | uses: actions/cache@v4 39 | with: 40 | path: target 41 | key: ${{ runner.os }}-cargo-target-${{ hashFiles('**/Cargo.lock') }} 42 | restore-keys: | 43 | ${{ runner.os }}-cargo-target- 44 | 45 | - name: Install protoc 46 | uses: taiki-e/install-action@v2 47 | with: 48 | tool: protoc 49 | 50 | - name: Run cargo check 51 | run: cargo check --tests 52 | 53 | test: 54 | name: Test Suite 55 | runs-on: ${{ matrix.os }} 56 | strategy: 57 | fail-fast: false 58 | matrix: 59 | os: [ubuntu-latest, macos-latest, windows-latest] 60 | steps: 61 | - name: Checkout sources 62 | uses: actions/checkout@v4 63 | 64 | - name: Install toolchain 65 | id: rust-toolchain 66 | uses: dtolnay/rust-toolchain@stable 67 | 68 | - name: Cache cargo registry 69 | uses: actions/cache@v4 70 | with: 71 | path: ~/.cargo/registry 72 | key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} 73 | restore-keys: | 74 | ${{ runner.os }}-cargo-registry- 75 | 76 | - name: Cache cargo index 77 | uses: actions/cache@v4 78 | with: 79 | path: ~/.cargo/git 80 | key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} 81 | restore-keys: | 82 | ${{ runner.os }}-cargo-git- 83 | 84 | - name: Cache build 85 | uses: actions/cache@v4 86 | with: 87 | path: target 88 | key: ${{ runner.os }}-cargo-target-${{ hashFiles('**/Cargo.lock') }} 89 | restore-keys: | 90 | ${{ runner.os }}-cargo-target- 91 | 92 | - name: Install protoc 93 | uses: taiki-e/install-action@v2 94 | with: 95 | tool: protoc 96 | 97 | - name: Run cargo test regular features 98 | run: cargo test 99 | 100 | - name: Run cargo test no asm 101 | run: cargo test --features=no-asm 102 | 103 | - name: Run cargo test with parking_lot 104 | run: cargo test --features=parking_lot 105 | 106 | - name: Run cargo test shuttle 107 | run: cargo test --features=shuttle 108 | 109 | test-release: 110 | name: Test Suite Release 111 | runs-on: ${{ matrix.os }} 112 | strategy: 113 | fail-fast: false 114 | matrix: 115 | os: [ubuntu-latest, macos-latest, windows-latest] 116 | steps: 117 | - name: Checkout sources 118 | uses: actions/checkout@v4 119 | 120 | - name: Install toolchain 121 | id: rust-toolchain 122 | uses: dtolnay/rust-toolchain@stable 123 | 124 | - name: Cache cargo registry 125 | uses: actions/cache@v4 126 | with: 127 | path: ~/.cargo/registry 128 | key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} 129 | restore-keys: | 130 | ${{ runner.os }}-cargo-registry- 131 | 132 | - name: Cache cargo index 133 | uses: actions/cache@v4 134 | with: 135 | path: ~/.cargo/git 136 | key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} 137 | restore-keys: | 138 | ${{ runner.os }}-cargo-git- 139 | 140 | - name: Cache build 141 | uses: actions/cache@v4 142 | with: 143 | path: target 144 | key: ${{ runner.os }}-cargo-target-${{ hashFiles('**/Cargo.lock') }} 145 | restore-keys: | 146 | ${{ runner.os }}-cargo-target- 147 | 148 | - name: Install protoc 149 | uses: taiki-e/install-action@v2 150 | with: 151 | tool: protoc 152 | 153 | - name: Run cargo test release regular features 154 | run: cargo test --release 155 | 156 | - name: Run cargo test release no asm 157 | run: cargo test --features=no-asm --release 158 | 159 | - name: Run cargo test release with parking_lot 160 | run: cargo test --features=parking_lot --release 161 | 162 | - name: Run cargo test release shuttle 163 | run: cargo test --no-default-features --features=shuttle --release 164 | 165 | lints: 166 | name: Lints 167 | runs-on: ubuntu-latest 168 | steps: 169 | - name: Checkout sources 170 | uses: actions/checkout@v4 171 | 172 | - name: Install toolchain 173 | id: rust-toolchain 174 | uses: dtolnay/rust-toolchain@stable 175 | with: 176 | components: rustfmt, clippy 177 | 178 | - name: Cache cargo registry 179 | uses: actions/cache@v4 180 | with: 181 | path: ~/.cargo/registry 182 | key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} 183 | restore-keys: | 184 | ${{ runner.os }}-cargo-registry- 185 | 186 | - name: Cache cargo index 187 | uses: actions/cache@v4 188 | with: 189 | path: ~/.cargo/git 190 | key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} 191 | restore-keys: | 192 | ${{ runner.os }}-cargo-git- 193 | 194 | - name: Cache build 195 | uses: actions/cache@v4 196 | with: 197 | path: target 198 | key: ${{ runner.os }}-cargo-target-${{ hashFiles('**/Cargo.lock') }} 199 | restore-keys: | 200 | ${{ runner.os }}-cargo-target- 201 | 202 | - name: Install protoc 203 | uses: taiki-e/install-action@v2 204 | with: 205 | tool: protoc 206 | 207 | - name: Run cargo fmt 208 | run: cargo fmt --all -- --check 209 | 210 | - name: Run cargo clippy 211 | run: cargo clippy --tests -- -D warnings 212 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | name: Build and upload assets 2 | on: 3 | release: 4 | types: [ published ] 5 | 6 | jobs: 7 | build: 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | include: 13 | - os: ubuntu-20.04 14 | TARGET: linux-gnu/amd64 15 | - os: ubuntu-latest 16 | TARGET: linux-musl/amd64 17 | - os: ubuntu-latest 18 | TARGET: linux-gnu/aarch64 19 | - os: ubuntu-latest 20 | TARGET: android/aarch64 21 | - os: windows-latest 22 | TARGET: windows-msvc/amd64 23 | - os: macos-latest 24 | TARGET: macos/amd64 25 | - os: macos-latest 26 | TARGET: macos/aarch64 27 | name: Build on ${{ matrix.TARGET }} 28 | steps: 29 | - name: Checkout sources 30 | uses: actions/checkout@v4 31 | 32 | - name: Install toolchain 33 | uses: dtolnay/rust-toolchain@stable 34 | 35 | - name: Install protoc 36 | uses: taiki-e/install-action@v2 37 | with: 38 | tool: protoc 39 | 40 | - name: Create bin directory 41 | run: mkdir bin 42 | 43 | - name: Build on Linux GNU 44 | if: matrix.TARGET == 'linux-gnu/amd64' 45 | run: | 46 | rustup target add x86_64-unknown-linux-gnu 47 | cargo build --target=x86_64-unknown-linux-gnu --release 48 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-linux-gnu-amd64.zip" 49 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-linux-gnu-amd64" 50 | strip ./target/x86_64-unknown-linux-gnu/release/spectre-miner 51 | mv ./target/x86_64-unknown-linux-gnu/release/spectre-miner ./bin/${asset_name} 52 | zip -r "${archive}" ./bin/${asset_name} 53 | 54 | # HiveOS. 55 | hiveos_asset_name="spectre-miner-${{ github.event.release.tag_name }}_hiveos" 56 | hiveos_archive="bin/${hiveos_asset_name}.tar.gz" 57 | cp -r ./hive-os ./bin/spectre-miner 58 | cp ./bin/${asset_name} ./bin/spectre-miner/spectre-miner 59 | sed 's/^ver="custom"/ver="${{ github.event.release.tag_name }}"/g' -i ./bin/spectre-miner/h-stats.sh 60 | tar -czvf "${hiveos_archive}" -C ./bin spectre-miner 61 | rm -r ./bin/spectre-miner 62 | 63 | # mmpOS. 64 | mmpos_asset_name="spectre-miner-${{ github.event.release.tag_name }}_mmpos" 65 | mmpos_archive="bin/${mmpos_asset_name}.tar.gz" 66 | cp -r ./mmpos ./bin/spectre-miner 67 | cp ./bin/${asset_name} ./bin/spectre-miner/spectre-miner 68 | sed 's/^ver="custom"/ver="${{ github.event.release.tag_name }}"/g' -i ./bin/spectre-miner/mmp-external.conf 69 | tar -czvf "${mmpos_archive}" -C ./bin spectre-miner 70 | rm -r ./bin/spectre-miner 71 | 72 | # Cleanup. 73 | rm ./bin/${asset_name} 74 | 75 | - name: Build on Linux musl 76 | if: matrix.TARGET == 'linux-musl/amd64' 77 | run: | 78 | sudo apt-get install -y musl-tools 79 | rustup target add x86_64-unknown-linux-musl 80 | cargo build --target=x86_64-unknown-linux-musl --release 81 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-linux-musl-amd64.zip" 82 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-linux-musl-amd64" 83 | strip ./target/x86_64-unknown-linux-musl/release/spectre-miner 84 | mv ./target/x86_64-unknown-linux-musl/release/spectre-miner ./bin/${asset_name} 85 | zip -r "${archive}" ./bin/${asset_name} 86 | rm ./bin/${asset_name} 87 | 88 | - name: Build on Linux for linux-gnu/aarch64 89 | if: matrix.TARGET == 'linux-gnu/aarch64' 90 | env: 91 | TARGET_CC: aarch64-linux-gnu-gcc 92 | TARGET_CXX: aarch64-linux-gnu-g++ 93 | RUSTFLAGS: -C linker=aarch64-linux-gnu-gcc 94 | run: | 95 | sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 96 | rustup target add aarch64-unknown-linux-gnu 97 | cargo build --target=aarch64-unknown-linux-gnu --release 98 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-linux-gnu-arm64.zip" 99 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-linux-gnu-arm64" 100 | mv ./target/aarch64-unknown-linux-gnu/release/spectre-miner ./bin/${asset_name} 101 | zip -r "${archive}" ./bin/${asset_name} 102 | rm ./bin/${asset_name} 103 | 104 | - name: Build for Android ARM64 105 | if: matrix.TARGET == 'android/aarch64' 106 | env: 107 | TARGET_CC: aarch64-linux-android21-clang 108 | TARGET_CXX: aarch64-linux-android21-clang++ 109 | RUSTFLAGS: -C linker=aarch64-linux-android21-clang 110 | run: | 111 | curl -sSL https://dl.google.com/android/repository/android-ndk-r27c-linux.zip -o android-ndk.zip 112 | unzip android-ndk.zip -d $HOME 113 | export ANDROID_NDK_HOME=$HOME/android-ndk-r27c 114 | export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH 115 | 116 | rustup target add aarch64-linux-android 117 | cargo build --target=aarch64-linux-android --release 118 | 119 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-android-arm64.zip" 120 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-android-arm64" 121 | mv ./target/aarch64-linux-android/release/spectre-miner ./bin/${asset_name} 122 | zip -r "${archive}" ./bin/${asset_name} 123 | rm ./bin/${asset_name} 124 | 125 | - name: Build on Windows 126 | if: matrix.TARGET == 'windows-msvc/amd64' 127 | shell: bash 128 | run: | 129 | rustup target add x86_64-pc-windows-msvc 130 | cargo build --target=x86_64-pc-windows-msvc --release 131 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-win64-amd64.zip" 132 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-win64-amd64.exe" 133 | mv ./target/x86_64-pc-windows-msvc/release/spectre-miner.exe ./bin/${asset_name} 134 | 7z a -tzip -r "${archive}" bin/${asset_name} 135 | rm ./bin/${asset_name} 136 | 137 | - name: Build on MacOS for x86_64 138 | if: matrix.TARGET == 'macos/amd64' 139 | run: | 140 | rustup target add x86_64-apple-darwin 141 | cargo build --target=x86_64-apple-darwin --release 142 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-osx-amd64.zip" 143 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-osx-amd64" 144 | mv ./target/x86_64-apple-darwin/release/spectre-miner ./bin/${asset_name} 145 | zip -r "${archive}" ./bin/${asset_name} 146 | rm ./bin/${asset_name} 147 | 148 | - name: Build on MacOS for M1/2 149 | if: matrix.TARGET == 'macos/aarch64' 150 | run: | 151 | rustup target add aarch64-apple-darwin 152 | cargo build --target=aarch64-apple-darwin --release 153 | archive="bin/spectre-miner-${{ github.event.release.tag_name }}-osx-aarch64.zip" 154 | asset_name="spectre-miner-${{ github.event.release.tag_name }}-osx-aarch64" 155 | mv ./target/aarch64-apple-darwin/release/spectre-miner ./bin/${asset_name} 156 | zip -r "${archive}" ./bin/${asset_name} 157 | rm ./bin/${asset_name} 158 | 159 | - name: Upload release asset 160 | uses: softprops/action-gh-release@v2 161 | with: 162 | files: | 163 | bin/*.zip 164 | bin/*.tar.gz 165 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 120 2 | use_field_init_shorthand = true 3 | use_try_shorthand = true 4 | use_small_heuristics = "Max" 5 | newline_style = "unix" 6 | edition = "2021" -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spectre-miner" 3 | version = "0.3.18" 4 | edition = "2021" 5 | license = "MIT/Apache-2.0" 6 | authors = ["Spectre developers"] 7 | repository = "https://github.com/spectre-project/spectre-miner" 8 | readme = "README.md" 9 | description = "A Spectre high performance CPU miner" 10 | categories = ["command-line-utilities"] 11 | keywords = ["blockchain", "cli"] 12 | include = [ 13 | "src/**", 14 | "proto/**", 15 | "Cargo.toml", 16 | "Cargo.lock", 17 | "build.rs", 18 | "LICENSE-MIT", 19 | "LICENSE-APACHE", 20 | "README.md", 21 | ] 22 | 23 | [dependencies] 24 | tonic = "0.10" 25 | tokio = { version = "1", features = ["macros", "rt-multi-thread"] } 26 | prost = "0.12" 27 | tokio-stream = "0.1" 28 | num_cpus = "1" 29 | rand = "0.8" 30 | blake2b_simd = "1.0.0" 31 | clap = { version = "4", features = ["derive", "color"] } 32 | log = "0.4" 33 | env_logger = "0.10" 34 | arc-swap = "1.6.0" 35 | keccak = { version = "0.1", optional = true } 36 | parking = { package = "parking_lot", version = "0.12", optional = true } 37 | shuttle = { version = "0.6", optional = true } 38 | chrono = "0.4" 39 | spectrex = ">=0.3.17" 40 | sysinfo = "0.30.12" 41 | 42 | [features] 43 | default = ["keccak?/asm"] 44 | parking_lot = ["parking", "tokio/parking_lot"] 45 | bench = [] 46 | no-asm = ["keccak"] 47 | 48 | [target.'cfg(not(target_arch = "x86_64"))'.dependencies] 49 | keccak = "0.1" 50 | 51 | [profile.release] 52 | lto = true 53 | codegen-units = 1 54 | strip = true 55 | 56 | [build-dependencies] 57 | tonic-build = { version = "0.10", default-features = false, features = ["prost", "transport"] } 58 | cc = "1" 59 | 60 | [dev-dependencies] 61 | sha3 = "0.10" 62 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spectre Miner 2 | 3 | [![Build status](https://github.com/spectre-project/spectre-miner/actions/workflows/ci.yaml/badge.svg)](https://github.com/spectre-project/spectre-miner/actions/workflows/ci.yaml) 4 | [![GitHub release](https://img.shields.io/github/v/release/spectre-project/spectre-miner.svg)](https://github.com/spectre-project/spectre-miner/releases) 5 | [![GitHub license](https://img.shields.io/github/license/spectre-project/spectre-miner.svg)](https://github.com/spectre-project/spectre-miner/blob/main/LICENSE-APACHE) 6 | [![GitHub downloads](https://img.shields.io/github/downloads/spectre-project/spectre-miner/total.svg)](https://github.com/spectre-project/spectre-miner/releases) 7 | [![Join the Spectre Discord Server](https://img.shields.io/discord/1233113243741061240.svg?label=&logo=discord&logoColor=ffffff&color=5865F2)](https://discord.com/invite/FZPYpwszcF) 8 | 9 | A Rust binary for mining Spectre with the [SpectreX](https://github.com/spectre-project/rusty-spectrex) 10 | algorithm. 11 | 12 | ## Installation 13 | 14 | ### Install from Binaries 15 | 16 | Pre-compiled binaries for Linux `x86_64`, Windows `x64` and macOS `x64` 17 | and `aarch64` can be downloaded from the [GitHub release](https://github.com/spectre-project/spectre-miner/releases) 18 | page. 19 | 20 | ### Build from Source 21 | 22 | To compile from source you need to have a working Rust and Cargo 23 | installation, run the following commands to build `spectre-miner`: 24 | 25 | ``` 26 | git clone https://github.com/spectre-project/spectre-miner 27 | cd spectre-miner 28 | cargo build --release 29 | ``` 30 | 31 | ## Usage 32 | 33 | To start mining you need to run a Spectre full node. It is highly 34 | recommended to run the [Spectre on Rust](https://github.com/spectre-project/rusty-spectre) 35 | version. As a fallback, deprecated and legacy option, the 36 | [Spectre Golang Node](https://github.com/spectre-project/spectred) 37 | is supported as well. You need to have an address to send the mining 38 | rewards to. Running `spectre-miner -h` will show all available command 39 | line options: 40 | 41 | ``` 42 | A Spectre high performance CPU miner 43 | 44 | Usage: spectre-miner [OPTIONS] --mining-address 45 | 46 | Options: 47 | -a, --mining-address 48 | The Spectre address for the miner reward 49 | -s, --spectred-address 50 | The IP of the spectred instance [default: 127.0.0.1] 51 | -p, --port 52 | Spectred port [default: Mainnet = 18110, Testnet = 18210] 53 | -d, --debug 54 | Enable debug logging level 55 | --testnet 56 | Use testnet instead of mainnet [default: false] 57 | -t, --threads 58 | Amount of miner threads to launch [default: number of logical cpus] 59 | --devfund 60 | Mine a percentage of the blocks to the Spectre devfund [default: Off] 61 | --devfund-percent 62 | The percentage of blocks to send to the devfund [default: 1] 63 | --mine-when-not-synced 64 | Mine even when spectred says it is not synced, only useful when passing `--allow-submit-block-when-not-synced` to spectred [default: false] 65 | --throttle 66 | Throttle (milliseconds) between each pow hash generation (used for development testing) 67 | --altlogs 68 | Output logs in alternative format (same as spectred) 69 | -h, --help 70 | Print help 71 | -V, --version 72 | Print version 73 | ``` 74 | 75 | To start mining you just need to run the following: 76 | 77 | ``` 78 | ./spectre-miner --mining-address spectre:XXXXX 79 | ``` 80 | 81 | This will run the miner on all the available CPU cores. 82 | 83 | ## Hive OS and mmpOS 84 | 85 | You can always download the most recent HiveOS flight sheet and mmpOS miner profile from our website. 86 | 87 | - [HiveOS Flight Sheet](https://spectre-network.org/downloads/hive-os/) 88 | - [mmpOS Miner Profile](https://spectre-network.org/downloads/mmp-os/) 89 | 90 | ## Development Fund 91 | 92 | **NOTE: This feature is off by default** 93 | 94 | The devfund is a fund managed by the Spectre community in order to 95 | fund Spectre development. 96 | 97 | A miner that wants to mine a percentage into the dev-fund can pass the 98 | following flags: 99 | 100 | ``` 101 | ./spectre-miner --mining-address= --devfund=spectre:qrxf48dgrdkjxllxczek3uweuldtan9nanzjsavk0ak9ynwn0zsayjjh7upez 102 | ``` 103 | 104 | Without specifying `--devfund-percent` it will default to 1%. If you 105 | want to change the percentage, you can pass the option 106 | `--devfund-percent=XX.YY` to mine only XX.YY% of the blocks into the 107 | devfund. 108 | 109 | ## License 110 | 111 | Spectre miner is dual-licensed under the [MIT](https://github.com/spectre-project/spectre-miner/blob/main/LICENSE-MIT) 112 | and [Apache 2.0](https://github.com/spectre-project/spectre-miner/blob/main/LICENSE-APACHE) 113 | license. 114 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | fn main() -> Result<(), Box> { 4 | println!("cargo:rerun-if-changed=proto"); 5 | println!("cargo:rerun-if-changed=src/asm"); 6 | tonic_build::configure() 7 | .build_server(false) 8 | // .type_attribute(".", "#[derive(Debug)]") 9 | .compile( 10 | &["proto/rpc.proto", "proto/p2p.proto", "proto/messages.proto"], 11 | &["proto"], 12 | )?; 13 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 14 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 15 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 16 | 17 | if target_arch == "x86_64" { 18 | let mut builder = cc::Build::new(); 19 | builder.flag("-c"); 20 | match target_os.as_str() { 21 | "macos" => builder.file("src/asm/keccakf1600_x86-64-osx.s"), 22 | "linux" => builder.file("src/asm/keccakf1600_x86-64-elf.s"), 23 | "windows" if target_env == "gnu" => builder.file("src/asm/keccakf1600_x86-64-mingw64.s"), 24 | "windows" if target_env == "msvc" => builder.file("src/asm/keccakf1600_x86-64-msvc.asm"), 25 | _ => unimplemented!("Unsupported OS"), 26 | }; 27 | builder.compile("libkeccak.a"); 28 | } 29 | Ok(()) 30 | } 31 | -------------------------------------------------------------------------------- /hive-os/h-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | 4 | # Extract the dynamic part (assuming 'nproc' command is your dynamic part) 5 | DYNAMIC_PART=$(echo "$CUSTOM_USER_CONFIG" | grep -oP '\$\((nproc.*)\)') 6 | 7 | if [ ! -z "$DYNAMIC_PART" ]; then 8 | EVALUATED_DYNAMIC_PART=$(eval echo "$DYNAMIC_PART") 9 | eval echo "$DYNAMIC_PART" > /dev/null 2>&1 10 | 11 | if [ $? -eq 0 ]; then 12 | SAFE_DYNAMIC_PART=$(printf '%s\n' "$DYNAMIC_PART" | sed 's:[][\/.^$*]:\\&:g') 13 | MODIFIED_CONFIG=$(echo "$CUSTOM_USER_CONFIG" | sed "s/$SAFE_DYNAMIC_PART/$EVALUATED_DYNAMIC_PART/") 14 | conf="$MODIFIED_CONFIG" 15 | echo "Modified config after removing executed command: $conf" 16 | else 17 | echo "Error in executing dynamic part. No modifications made." 18 | conf="$CUSTOM_USER_CONFIG" 19 | fi 20 | else 21 | echo "No dynamic part found. No modifications made." 22 | conf="$CUSTOM_USER_CONFIG" 23 | fi 24 | 25 | echo "$conf" 26 | echo "$conf" > "$CUSTOM_CONFIG_FILENAME" 27 | 28 | echo "Wrote config to $CUSTOM_CONFIG_FILENAME" 29 | echo "The contents of the config file are:" 30 | cat "$CUSTOM_CONFIG_FILENAME" -------------------------------------------------------------------------------- /hive-os/h-manifest.conf: -------------------------------------------------------------------------------- 1 | MINER_NAME=spectre-miner 2 | MINER_LOG_BASENAME=/var/log/miner/$MINER_NAME/$MINER_NAME 3 | CUSTOM_LOG_BASENAME=/var/log/miner/custom/custom 4 | CUSTOM_CONFIG_BASENAME=/hive/miners/custom/$MINER_NAME 5 | CUSTOM_CONFIG_FILENAME=$CUSTOM_CONFIG_BASENAME/config.conf 6 | -------------------------------------------------------------------------------- /hive-os/h-run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Source the configuration file 4 | source h-manifest.conf 5 | 6 | # Define the custom log directory 7 | LOG_DIR=$(dirname "$CUSTOM_LOG_BASENAME") 8 | mkdir -p "$LOG_DIR" 9 | 10 | # Check if the custom config filename is defined 11 | if [[ -z ${CUSTOM_CONFIG_FILENAME:-} ]]; then 12 | echo "The config file is not defined" 13 | exit 1 14 | fi 15 | 16 | # Set the library path 17 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/hive/lib 18 | 19 | # Read the custom user configuration 20 | CUSTOM_USER_CONFIG=$(< "$CUSTOM_CONFIG_FILENAME") 21 | 22 | # Display the arguments 23 | echo "args: $CUSTOM_USER_CONFIG" 24 | 25 | MINER=spectre-miner 26 | 27 | # Remove the -arch argument and its value 28 | CLEAN=$(echo "$CUSTOM_USER_CONFIG" | sed -E 's/-arch [^ ]+ //') 29 | echo "args are now: $CLEAN" 30 | echo "We are using miner: $MINER" 31 | 32 | echo $(date +%s) > "/tmp/miner_start_time" 33 | /hive/miners/custom/$MINER/$MINER $CLEAN 2>&1 | tee -a ${CUSTOM_LOG_BASENAME}.log 34 | echo "Miner has exited" -------------------------------------------------------------------------------- /hive-os/h-stats.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source /hive/miners/custom/spectre-miner/h-manifest.conf 3 | 4 | # Reading log file content 5 | log_file="/var/log/miner/custom/custom.log" 6 | 7 | # Read the log file content 8 | log=$(<"$log_file") 9 | 10 | get_cpu_temps () { 11 | local t_core=$(cpu-temp) 12 | local l_num_cores=$1 13 | local l_temp= 14 | for (( i=0; i < l_num_cores; i++ )); do 15 | l_temp+="$t_core " 16 | done 17 | echo $l_temp | tr " " "\n" | jq -cs '.' 18 | } 19 | 20 | get_cpu_fans () { 21 | local t_fan=0 22 | local l_num_cores=$1 23 | local l_fan= 24 | for (( i=0; i < l_num_cores; i++ )); do 25 | l_fan+="$t_fan " 26 | done 27 | echo $l_fan | tr " " "\n" | jq -cs '.' 28 | } 29 | 30 | get_uptime(){ 31 | local start_time=$(cat "/tmp/miner_start_time") 32 | local current_time=$(date +%s) 33 | let uptime=current_time-start_time 34 | echo $uptime 35 | } 36 | 37 | uptime=$(get_uptime) 38 | 39 | # Extract the most recent total khs value from the log 40 | total_khs=$(grep -oP "hashrate is: \K\d+.\d+" <<< "$log" | tail -n1) 41 | if [[ -z $total_khs ]]; then 42 | total_khs=0 43 | fi 44 | 45 | # Count the number of blocks submitted successfully 46 | ac=$(grep -coP "Block submitted successfully!" <<< "$log") 47 | if [[ -z $ac ]]; then 48 | ac=0 49 | fi 50 | 51 | rj=0 52 | ver="custom" 53 | algo="spectrex" 54 | cpu_temp=$(/hive/sbin/cpu-temp) 55 | hs_units="hs" 56 | 57 | # Construct JSON stats 58 | stats=$(jq -nc \ 59 | --arg total_khs "$total_khs" \ 60 | --arg khs "$total_khs" \ 61 | --arg hs_units "$hs_units" \ 62 | --arg hs "[$total_khs]" \ 63 | --arg temp "[$cpu_temp]" \ 64 | --arg uptime "$uptime" \ 65 | --arg ver "$ver" \ 66 | --argjson ac "$ac" \ 67 | --argjson rj "$rj" \ 68 | --arg algo "$algo" \ 69 | '{$total_khs, $khs, $hs_units, $hs, $temp, $uptime, $ver, ar: [$ac, $rj], $algo }') 70 | 71 | echo "khs: $hs" 72 | echo "stats: $stats" 73 | echo "----------" 74 | -------------------------------------------------------------------------------- /mmpos/mmp-external.conf: -------------------------------------------------------------------------------- 1 | # The name of the miner ex. myfirstminer 2 | EXTERNAL_NAME=spectre-miner 3 | # Miner version 4 | EXTERNAL_VERSION=custom 5 | -------------------------------------------------------------------------------- /mmpos/mmp-stats.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | GPU_COUNT=$1 3 | LOG_FILE=$2 4 | cd `dirname $0` 5 | [ -r mmp-external.conf ] && . mmp-external.conf 6 | 7 | get_cpu_hashes() { 8 | hash='' 9 | local hs=$(grep -oP "hashrate is: \K\d+.\d+" <<< $(cat $LOG_FILE) | tail -n1) 10 | if [[ -z "$hs" ]]; then 11 | hs="0" 12 | fi 13 | if [[ $hs > 0 ]]; then 14 | hash=$(echo "$hs") 15 | fi 16 | } 17 | 18 | get_miner_stats() { 19 | stats= 20 | local hash= 21 | get_cpu_hashes 22 | # A/R shares by pool 23 | local acc=$(grep -coP "Block submitted successfully!" <<< $(cat $LOG_FILE)) 24 | # local inv=$(get_miner_shares_inv) 25 | # local rj=$(get_miner_shares_rj) 26 | 27 | stats=$(jq -nc \ 28 | --argjson hash "$(echo "${hash[@]}" | tr " " "\n" | jq -cs '.')" \ 29 | --arg busid "cpu" \ 30 | --arg units "khs" \ 31 | --arg ac "$acc" --arg inv "0" --arg rj "0" \ 32 | --arg miner_version "$EXTERNAL_VERSION" \ 33 | --arg miner_name "$EXTERNAL_NAME" \ 34 | '{busid: [$busid], $hash, $units, air: [$ac, $inv, $rj], miner_name: $miner_name, miner_version: $miner_version}') 35 | echo "$stats" 36 | } 37 | get_miner_stats -------------------------------------------------------------------------------- /proto/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package protowire; 3 | 4 | option go_package = "github.com/spectre-project/spectred/protowire"; 5 | 6 | import "p2p.proto"; 7 | import "rpc.proto"; 8 | 9 | message SpectredMessage { 10 | oneof payload { 11 | AddressesMessage addresses = 1; 12 | BlockMessage block = 2; 13 | TransactionMessage transaction = 3; 14 | BlockLocatorMessage blockLocator = 5; 15 | RequestAddressesMessage requestAddresses = 6; 16 | RequestRelayBlocksMessage requestRelayBlocks = 10; 17 | RequestTransactionsMessage requestTransactions = 12; 18 | BlockMessage ibdBlock = 13; 19 | InvRelayBlockMessage invRelayBlock = 14; 20 | InvTransactionsMessage invTransactions = 15; 21 | PingMessage ping = 16; 22 | PongMessage pong = 17; 23 | VerackMessage verack = 19; 24 | VersionMessage version = 20; 25 | TransactionNotFoundMessage transactionNotFound = 21; 26 | RejectMessage reject = 22; 27 | PruningPointUtxoSetChunkMessage pruningPointUtxoSetChunk = 25; 28 | RequestIBDBlocksMessage requestIBDBlocks = 26; 29 | UnexpectedPruningPointMessage unexpectedPruningPoint = 27; 30 | IbdBlockLocatorMessage ibdBlockLocator = 30; 31 | IbdBlockLocatorHighestHashMessage ibdBlockLocatorHighestHash = 31; 32 | RequestNextPruningPointUtxoSetChunkMessage requestNextPruningPointUtxoSetChunk = 33; 33 | DonePruningPointUtxoSetChunksMessage donePruningPointUtxoSetChunks = 34; 34 | IbdBlockLocatorHighestHashNotFoundMessage ibdBlockLocatorHighestHashNotFound = 35; 35 | BlockWithTrustedDataMessage blockWithTrustedData = 36; 36 | DoneBlocksWithTrustedDataMessage doneBlocksWithTrustedData = 37; 37 | RequestPruningPointAndItsAnticoneMessage requestPruningPointAndItsAnticone = 40; 38 | BlockHeadersMessage blockHeaders = 41; 39 | RequestNextHeadersMessage requestNextHeaders = 42; 40 | DoneHeadersMessage DoneHeaders = 43; 41 | RequestPruningPointUTXOSetMessage requestPruningPointUTXOSet = 44; 42 | RequestHeadersMessage requestHeaders = 45; 43 | RequestBlockLocatorMessage requestBlockLocator = 46; 44 | PruningPointsMessage pruningPoints = 47; 45 | RequestPruningPointProofMessage requestPruningPointProof = 48; 46 | PruningPointProofMessage pruningPointProof = 49; 47 | ReadyMessage ready = 50; 48 | BlockWithTrustedDataV4Message blockWithTrustedDataV4 = 51; 49 | TrustedDataMessage trustedData = 52; 50 | RequestIBDChainBlockLocatorMessage requestIBDChainBlockLocator = 53; 51 | IbdChainBlockLocatorMessage ibdChainBlockLocator = 54; 52 | RequestAnticoneMessage requestAnticone = 55; 53 | RequestNextPruningPointAndItsAnticoneBlocksMessage requestNextPruningPointAndItsAnticoneBlocks = 56; 54 | 55 | GetCurrentNetworkRequestMessage getCurrentNetworkRequest = 1001; 56 | GetCurrentNetworkResponseMessage getCurrentNetworkResponse = 1002; 57 | SubmitBlockRequestMessage submitBlockRequest = 1003; 58 | SubmitBlockResponseMessage submitBlockResponse = 1004; 59 | GetBlockTemplateRequestMessage getBlockTemplateRequest = 1005; 60 | GetBlockTemplateResponseMessage getBlockTemplateResponse = 1006; 61 | NotifyBlockAddedRequestMessage notifyBlockAddedRequest = 1007; 62 | NotifyBlockAddedResponseMessage notifyBlockAddedResponse = 1008; 63 | BlockAddedNotificationMessage blockAddedNotification = 1009; 64 | GetPeerAddressesRequestMessage getPeerAddressesRequest = 1010; 65 | GetPeerAddressesResponseMessage getPeerAddressesResponse = 1011; 66 | GetSelectedTipHashRequestMessage getSelectedTipHashRequest = 1012; 67 | GetSelectedTipHashResponseMessage getSelectedTipHashResponse = 1013; 68 | GetMempoolEntryRequestMessage getMempoolEntryRequest = 1014; 69 | GetMempoolEntryResponseMessage getMempoolEntryResponse = 1015; 70 | GetConnectedPeerInfoRequestMessage getConnectedPeerInfoRequest = 1016; 71 | GetConnectedPeerInfoResponseMessage getConnectedPeerInfoResponse = 1017; 72 | AddPeerRequestMessage addPeerRequest = 1018; 73 | AddPeerResponseMessage addPeerResponse = 1019; 74 | SubmitTransactionRequestMessage submitTransactionRequest = 1020; 75 | SubmitTransactionResponseMessage submitTransactionResponse = 1021; 76 | NotifyVirtualSelectedParentChainChangedRequestMessage notifyVirtualSelectedParentChainChangedRequest = 1022; 77 | NotifyVirtualSelectedParentChainChangedResponseMessage notifyVirtualSelectedParentChainChangedResponse = 1023; 78 | VirtualSelectedParentChainChangedNotificationMessage virtualSelectedParentChainChangedNotification = 1024; 79 | GetBlockRequestMessage getBlockRequest = 1025; 80 | GetBlockResponseMessage getBlockResponse = 1026; 81 | GetSubnetworkRequestMessage getSubnetworkRequest = 1027; 82 | GetSubnetworkResponseMessage getSubnetworkResponse = 1028; 83 | GetVirtualSelectedParentChainFromBlockRequestMessage getVirtualSelectedParentChainFromBlockRequest = 1029; 84 | GetVirtualSelectedParentChainFromBlockResponseMessage getVirtualSelectedParentChainFromBlockResponse = 1030; 85 | GetBlocksRequestMessage getBlocksRequest = 1031; 86 | GetBlocksResponseMessage getBlocksResponse = 1032; 87 | GetBlockCountRequestMessage getBlockCountRequest = 1033; 88 | GetBlockCountResponseMessage getBlockCountResponse = 1034; 89 | GetBlockDagInfoRequestMessage getBlockDagInfoRequest = 1035; 90 | GetBlockDagInfoResponseMessage getBlockDagInfoResponse = 1036; 91 | ResolveFinalityConflictRequestMessage resolveFinalityConflictRequest = 1037; 92 | ResolveFinalityConflictResponseMessage resolveFinalityConflictResponse = 1038; 93 | NotifyFinalityConflictsRequestMessage notifyFinalityConflictsRequest = 1039; 94 | NotifyFinalityConflictsResponseMessage notifyFinalityConflictsResponse = 1040; 95 | FinalityConflictNotificationMessage finalityConflictNotification = 1041; 96 | FinalityConflictResolvedNotificationMessage finalityConflictResolvedNotification = 1042; 97 | GetMempoolEntriesRequestMessage getMempoolEntriesRequest = 1043; 98 | GetMempoolEntriesResponseMessage getMempoolEntriesResponse = 1044; 99 | ShutDownRequestMessage shutDownRequest = 1045; 100 | ShutDownResponseMessage shutDownResponse = 1046; 101 | GetHeadersRequestMessage getHeadersRequest = 1047; 102 | GetHeadersResponseMessage getHeadersResponse = 1048; 103 | NotifyUtxosChangedRequestMessage notifyUtxosChangedRequest = 1049; 104 | NotifyUtxosChangedResponseMessage notifyUtxosChangedResponse = 1050; 105 | UtxosChangedNotificationMessage utxosChangedNotification = 1051; 106 | GetUtxosByAddressesRequestMessage getUtxosByAddressesRequest = 1052; 107 | GetUtxosByAddressesResponseMessage getUtxosByAddressesResponse = 1053; 108 | GetVirtualSelectedParentBlueScoreRequestMessage getVirtualSelectedParentBlueScoreRequest = 1054; 109 | GetVirtualSelectedParentBlueScoreResponseMessage getVirtualSelectedParentBlueScoreResponse = 1055; 110 | NotifyVirtualSelectedParentBlueScoreChangedRequestMessage notifyVirtualSelectedParentBlueScoreChangedRequest = 1056; 111 | NotifyVirtualSelectedParentBlueScoreChangedResponseMessage notifyVirtualSelectedParentBlueScoreChangedResponse = 1057; 112 | VirtualSelectedParentBlueScoreChangedNotificationMessage virtualSelectedParentBlueScoreChangedNotification = 1058; 113 | BanRequestMessage banRequest = 1059; 114 | BanResponseMessage banResponse = 1060; 115 | UnbanRequestMessage unbanRequest = 1061; 116 | UnbanResponseMessage unbanResponse = 1062; 117 | GetInfoRequestMessage getInfoRequest = 1063; 118 | GetInfoResponseMessage getInfoResponse = 1064; 119 | StopNotifyingUtxosChangedRequestMessage stopNotifyingUtxosChangedRequest = 1065; 120 | StopNotifyingUtxosChangedResponseMessage stopNotifyingUtxosChangedResponse = 1066; 121 | NotifyPruningPointUTXOSetOverrideRequestMessage notifyPruningPointUTXOSetOverrideRequest = 1067; 122 | NotifyPruningPointUTXOSetOverrideResponseMessage notifyPruningPointUTXOSetOverrideResponse = 1068; 123 | PruningPointUTXOSetOverrideNotificationMessage pruningPointUTXOSetOverrideNotification = 1069; 124 | StopNotifyingPruningPointUTXOSetOverrideRequestMessage stopNotifyingPruningPointUTXOSetOverrideRequest = 1070; 125 | StopNotifyingPruningPointUTXOSetOverrideResponseMessage stopNotifyingPruningPointUTXOSetOverrideResponse = 1071; 126 | EstimateNetworkHashesPerSecondRequestMessage estimateNetworkHashesPerSecondRequest = 1072; 127 | EstimateNetworkHashesPerSecondResponseMessage estimateNetworkHashesPerSecondResponse = 1073; 128 | NotifyVirtualDaaScoreChangedRequestMessage notifyVirtualDaaScoreChangedRequest = 1074; 129 | NotifyVirtualDaaScoreChangedResponseMessage notifyVirtualDaaScoreChangedResponse = 1075; 130 | VirtualDaaScoreChangedNotificationMessage virtualDaaScoreChangedNotification = 1076; 131 | GetBalanceByAddressRequestMessage getBalanceByAddressRequest = 1077; 132 | GetBalanceByAddressResponseMessage getBalanceByAddressResponse = 1078; 133 | GetBalancesByAddressesRequestMessage getBalancesByAddressesRequest = 1079; 134 | GetBalancesByAddressesResponseMessage getBalancesByAddressesResponse = 1080; 135 | NotifyNewBlockTemplateRequestMessage notifyNewBlockTemplateRequest = 1081; 136 | NotifyNewBlockTemplateResponseMessage notifyNewBlockTemplateResponse = 1082; 137 | NewBlockTemplateNotificationMessage newBlockTemplateNotification = 1083; 138 | GetMempoolEntriesByAddressesRequestMessage getMempoolEntriesByAddressesRequest = 1084; 139 | GetMempoolEntriesByAddressesResponseMessage getMempoolEntriesByAddressesResponse = 1085; 140 | GetCoinSupplyRequestMessage getCoinSupplyRequest = 1086; 141 | GetCoinSupplyResponseMessage getCoinSupplyResponse= 1087; 142 | } 143 | } 144 | 145 | service P2P { 146 | rpc MessageStream (stream SpectredMessage) returns (stream SpectredMessage) {} 147 | } 148 | 149 | service RPC { 150 | rpc MessageStream (stream SpectredMessage) returns (stream SpectredMessage) {} 151 | } 152 | -------------------------------------------------------------------------------- /proto/p2p.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package protowire; 3 | 4 | option go_package = "github.com/spectre-project/spectred/protowire"; 5 | 6 | message RequestAddressesMessage{ 7 | bool includeAllSubnetworks = 1; 8 | SubnetworkId subnetworkId = 2; 9 | } 10 | 11 | message AddressesMessage{ 12 | repeated NetAddress addressList = 1; 13 | } 14 | 15 | message NetAddress{ 16 | int64 timestamp = 1; 17 | bytes ip = 3; 18 | uint32 port = 4; 19 | } 20 | 21 | message SubnetworkId{ 22 | bytes bytes = 1; 23 | } 24 | 25 | message TransactionMessage{ 26 | uint32 version = 1; 27 | repeated TransactionInput inputs = 2; 28 | repeated TransactionOutput outputs = 3; 29 | uint64 lockTime = 4; 30 | SubnetworkId subnetworkId = 5; 31 | uint64 gas = 6; 32 | bytes payload = 8; 33 | uint64 mass = 9; 34 | } 35 | 36 | message TransactionInput{ 37 | Outpoint previousOutpoint = 1; 38 | bytes signatureScript = 2; 39 | uint64 sequence = 3; 40 | uint32 sigOpCount = 4; 41 | } 42 | 43 | message Outpoint{ 44 | TransactionId transactionId = 1; 45 | uint32 index = 2; 46 | } 47 | 48 | message TransactionId{ 49 | bytes bytes = 1; 50 | } 51 | message ScriptPublicKey { 52 | bytes script = 1; 53 | uint32 version = 2; 54 | } 55 | 56 | message TransactionOutput{ 57 | uint64 value = 1; 58 | ScriptPublicKey scriptPublicKey = 2; 59 | } 60 | 61 | message BlockMessage{ 62 | BlockHeader header = 1; 63 | repeated TransactionMessage transactions = 2; 64 | } 65 | 66 | message BlockHeader{ 67 | uint32 version = 1; 68 | repeated BlockLevelParents parents = 12; 69 | Hash hashMerkleRoot = 3; 70 | Hash acceptedIdMerkleRoot = 4; 71 | Hash utxoCommitment = 5; 72 | int64 timestamp = 6; 73 | uint32 bits = 7; 74 | uint64 nonce = 8; 75 | uint64 daaScore = 9; 76 | bytes blueWork = 10; 77 | Hash pruningPoint = 14; 78 | uint64 blueScore = 13; 79 | } 80 | 81 | message BlockLevelParents { 82 | repeated Hash parentHashes = 1; 83 | } 84 | 85 | message Hash{ 86 | bytes bytes = 1; 87 | } 88 | 89 | message RequestBlockLocatorMessage{ 90 | Hash highHash = 1; 91 | uint32 limit = 2; 92 | } 93 | 94 | message BlockLocatorMessage{ 95 | repeated Hash hashes = 1; 96 | } 97 | 98 | message RequestHeadersMessage{ 99 | Hash lowHash = 1; 100 | Hash highHash = 2; 101 | } 102 | 103 | message RequestNextHeadersMessage{ 104 | } 105 | 106 | message DoneHeadersMessage{ 107 | } 108 | 109 | message RequestRelayBlocksMessage{ 110 | repeated Hash hashes = 1; 111 | } 112 | 113 | message RequestTransactionsMessage { 114 | repeated TransactionId ids = 1; 115 | } 116 | 117 | message TransactionNotFoundMessage{ 118 | TransactionId id = 1; 119 | } 120 | 121 | message InvRelayBlockMessage{ 122 | Hash hash = 1; 123 | } 124 | 125 | message InvTransactionsMessage{ 126 | repeated TransactionId ids = 1; 127 | } 128 | 129 | message PingMessage{ 130 | uint64 nonce = 1; 131 | } 132 | 133 | message PongMessage{ 134 | uint64 nonce = 1; 135 | } 136 | 137 | message VerackMessage{ 138 | } 139 | 140 | message VersionMessage{ 141 | uint32 protocolVersion = 1; 142 | uint64 services = 2; 143 | int64 timestamp = 3; 144 | NetAddress address = 4; 145 | bytes id = 5; 146 | string userAgent = 6; 147 | bool disableRelayTx = 8; 148 | SubnetworkId subnetworkId = 9; 149 | string network = 10; 150 | } 151 | 152 | message RejectMessage{ 153 | string reason = 1; 154 | } 155 | 156 | message RequestPruningPointUTXOSetMessage{ 157 | Hash pruningPointHash = 1; 158 | } 159 | 160 | message PruningPointUtxoSetChunkMessage{ 161 | repeated OutpointAndUtxoEntryPair outpointAndUtxoEntryPairs = 1; 162 | } 163 | 164 | message OutpointAndUtxoEntryPair{ 165 | Outpoint outpoint = 1; 166 | UtxoEntry utxoEntry = 2; 167 | } 168 | 169 | message UtxoEntry { 170 | uint64 amount = 1; 171 | ScriptPublicKey scriptPublicKey = 2; 172 | uint64 blockDaaScore = 3; 173 | bool isCoinbase = 4; 174 | } 175 | 176 | message RequestNextPruningPointUtxoSetChunkMessage { 177 | } 178 | 179 | message DonePruningPointUtxoSetChunksMessage { 180 | } 181 | 182 | message RequestIBDBlocksMessage{ 183 | repeated Hash hashes = 1; 184 | } 185 | 186 | message UnexpectedPruningPointMessage{ 187 | } 188 | 189 | message IbdBlockLocatorMessage { 190 | Hash targetHash = 1; 191 | repeated Hash blockLocatorHashes = 2; 192 | } 193 | 194 | message RequestIBDChainBlockLocatorMessage{ 195 | Hash lowHash = 1; 196 | Hash highHash = 2; 197 | } 198 | 199 | message IbdChainBlockLocatorMessage { 200 | repeated Hash blockLocatorHashes = 1; 201 | } 202 | 203 | message RequestAnticoneMessage{ 204 | Hash blockHash = 1; 205 | Hash contextHash = 2; 206 | } 207 | 208 | message IbdBlockLocatorHighestHashMessage { 209 | Hash highestHash = 1; 210 | } 211 | 212 | message IbdBlockLocatorHighestHashNotFoundMessage { 213 | } 214 | 215 | message BlockHeadersMessage { 216 | repeated BlockHeader blockHeaders = 1; 217 | } 218 | 219 | message RequestPruningPointAndItsAnticoneMessage { 220 | } 221 | 222 | message RequestNextPruningPointAndItsAnticoneBlocksMessage{ 223 | } 224 | 225 | message BlockWithTrustedDataMessage { 226 | BlockMessage block = 1; 227 | uint64 daaScore = 2; 228 | repeated DaaBlock daaWindow = 3; 229 | repeated BlockGhostdagDataHashPair ghostdagData = 4; 230 | } 231 | 232 | message DaaBlock { 233 | BlockMessage block = 3; 234 | GhostdagData ghostdagData = 2; 235 | } 236 | 237 | message DaaBlockV4 { 238 | BlockHeader header = 1; 239 | GhostdagData ghostdagData = 2; 240 | } 241 | 242 | message BlockGhostdagDataHashPair { 243 | Hash hash = 1; 244 | GhostdagData ghostdagData = 2; 245 | } 246 | 247 | message GhostdagData { 248 | uint64 blueScore = 1; 249 | bytes blueWork = 2; 250 | Hash selectedParent = 3; 251 | repeated Hash mergeSetBlues = 4; 252 | repeated Hash mergeSetReds = 5; 253 | repeated BluesAnticoneSizes bluesAnticoneSizes = 6; 254 | } 255 | 256 | message BluesAnticoneSizes { 257 | Hash blueHash = 1; 258 | uint32 anticoneSize = 2; 259 | } 260 | 261 | message DoneBlocksWithTrustedDataMessage { 262 | } 263 | 264 | message PruningPointsMessage { 265 | repeated BlockHeader headers = 1; 266 | } 267 | 268 | message RequestPruningPointProofMessage { 269 | } 270 | 271 | message PruningPointProofMessage { 272 | repeated PruningPointProofHeaderArray headers = 1; 273 | } 274 | 275 | message PruningPointProofHeaderArray { 276 | repeated BlockHeader headers = 1; 277 | } 278 | 279 | message ReadyMessage { 280 | } 281 | 282 | message BlockWithTrustedDataV4Message { 283 | BlockMessage block = 1; 284 | repeated uint64 daaWindowIndices = 2; 285 | repeated uint64 ghostdagDataIndices = 3; 286 | } 287 | 288 | message TrustedDataMessage { 289 | repeated DaaBlockV4 daaWindow = 1; 290 | repeated BlockGhostdagDataHashPair ghostdagData = 2; 291 | } 292 | -------------------------------------------------------------------------------- /proto/rpc.proto: -------------------------------------------------------------------------------- 1 | // RPC-related types. Request messages, response messages, and dependant types. 2 | // 3 | // Clients are expected to build RequestMessages and wrap them in SpectredMessage. (see messages.proto) 4 | // 5 | // Having received a RequestMessage, (wrapped in a SpectredMessage) the RPC server will respond with a 6 | // ResponseMessage (likewise wrapped in a SpectredMessage) respective to the original RequestMessage. 7 | // 8 | // **IMPORTANT:** This API is a work in progress and is subject to break between versions. 9 | // 10 | syntax = "proto3"; 11 | package protowire; 12 | 13 | option go_package = "github.com/spectre-project/spectred/protowire"; 14 | 15 | // RPCError represents a generic non-internal error. 16 | // 17 | // Receivers of any ResponseMessage are expected to check whether its error field is not null. 18 | message RPCError{ 19 | string message = 1; 20 | } 21 | 22 | message RpcBlock { 23 | RpcBlockHeader header = 1; 24 | repeated RpcTransaction transactions = 2; 25 | RpcBlockVerboseData verboseData = 3; 26 | } 27 | 28 | message RpcBlockHeader { 29 | uint32 version = 1; 30 | repeated RpcBlockLevelParents parents = 12; 31 | string hashMerkleRoot = 3; 32 | string acceptedIdMerkleRoot = 4; 33 | string utxoCommitment = 5; 34 | int64 timestamp = 6; 35 | uint32 bits = 7; 36 | uint64 nonce = 8; 37 | uint64 daaScore = 9; 38 | string blueWork = 10; 39 | string pruningPoint = 14; 40 | uint64 blueScore = 13; 41 | } 42 | 43 | message RpcBlockLevelParents { 44 | repeated string parentHashes = 1; 45 | } 46 | 47 | message RpcBlockVerboseData{ 48 | string hash = 1; 49 | double difficulty = 11; 50 | string selectedParentHash = 13; 51 | repeated string transactionIds = 14; 52 | bool isHeaderOnly = 15; 53 | uint64 blueScore = 16; 54 | repeated string childrenHashes = 17; 55 | repeated string mergeSetBluesHashes = 18; 56 | repeated string mergeSetRedsHashes = 19; 57 | bool isChainBlock = 20; 58 | } 59 | 60 | message RpcTransaction { 61 | uint32 version = 1; 62 | repeated RpcTransactionInput inputs = 2; 63 | repeated RpcTransactionOutput outputs = 3; 64 | uint64 lockTime = 4; 65 | string subnetworkId = 5; 66 | uint64 gas = 6; 67 | string payload = 8; 68 | RpcTransactionVerboseData verboseData = 9; 69 | uint64 mass = 10; 70 | } 71 | 72 | message RpcTransactionInput { 73 | RpcOutpoint previousOutpoint = 1; 74 | string signatureScript = 2; 75 | uint64 sequence = 3; 76 | uint32 sigOpCount = 5; 77 | RpcTransactionInputVerboseData verboseData = 4; 78 | } 79 | 80 | message RpcScriptPublicKey { 81 | uint32 version = 1; 82 | string scriptPublicKey = 2; 83 | } 84 | 85 | message RpcTransactionOutput { 86 | uint64 amount = 1; 87 | RpcScriptPublicKey scriptPublicKey = 2; 88 | RpcTransactionOutputVerboseData verboseData = 3; 89 | } 90 | 91 | message RpcOutpoint { 92 | string transactionId = 1; 93 | uint32 index = 2; 94 | } 95 | 96 | message RpcUtxoEntry { 97 | uint64 amount = 1; 98 | RpcScriptPublicKey scriptPublicKey = 2; 99 | uint64 blockDaaScore = 3; 100 | bool isCoinbase = 4; 101 | } 102 | 103 | message RpcTransactionVerboseData{ 104 | string transactionId = 1; 105 | string hash = 2; 106 | uint64 mass = 4; 107 | string blockHash = 12; 108 | uint64 blockTime = 14; 109 | } 110 | 111 | message RpcTransactionInputVerboseData{ 112 | } 113 | 114 | message RpcTransactionOutputVerboseData{ 115 | string scriptPublicKeyType = 5; 116 | string scriptPublicKeyAddress = 6; 117 | } 118 | 119 | // GetCurrentNetworkRequestMessage requests the network spectred is currently running against. 120 | // 121 | // Possible networks are: Mainnet, Testnet, Simnet, Devnet 122 | message GetCurrentNetworkRequestMessage{ 123 | } 124 | 125 | message GetCurrentNetworkResponseMessage{ 126 | string currentNetwork = 1; 127 | RPCError error = 1000; 128 | } 129 | 130 | // SubmitBlockRequestMessage requests to submit a block into the DAG. 131 | // Blocks are generally expected to have been generated using the getBlockTemplate call. 132 | // 133 | // See: GetBlockTemplateRequestMessage 134 | message SubmitBlockRequestMessage{ 135 | RpcBlock block = 2; 136 | bool allowNonDAABlocks = 3; 137 | } 138 | 139 | message SubmitBlockResponseMessage{ 140 | enum RejectReason { 141 | NONE = 0; 142 | BLOCK_INVALID = 1; 143 | IS_IN_IBD = 2; 144 | } 145 | RejectReason rejectReason = 1; 146 | RPCError error = 1000; 147 | } 148 | 149 | // GetBlockTemplateRequestMessage requests a current block template. 150 | // Callers are expected to solve the block template and submit it using the submitBlock call 151 | // 152 | // See: SubmitBlockRequestMessage 153 | message GetBlockTemplateRequestMessage{ 154 | // Which spectre address should the coinbase block reward transaction pay into 155 | string payAddress = 1; 156 | string extraData = 2; 157 | } 158 | 159 | message GetBlockTemplateResponseMessage{ 160 | RpcBlock block = 3; 161 | 162 | // Whether spectred thinks that it's synced. 163 | // Callers are discouraged (but not forbidden) from solving blocks when spectred is not synced. 164 | // That is because when spectred isn't in sync with the rest of the network there's a high 165 | // chance the block will never be accepted, thus the solving effort would have been wasted. 166 | bool isSynced = 2; 167 | 168 | RPCError error = 1000; 169 | } 170 | 171 | // NotifyBlockAddedRequestMessage registers this connection for blockAdded notifications. 172 | // 173 | // See: BlockAddedNotificationMessage 174 | message NotifyBlockAddedRequestMessage{ 175 | } 176 | 177 | message NotifyBlockAddedResponseMessage{ 178 | RPCError error = 1000; 179 | } 180 | 181 | // BlockAddedNotificationMessage is sent whenever a blocks has been added (NOT accepted) 182 | // into the DAG. 183 | // 184 | // See: NotifyBlockAddedRequestMessage 185 | message BlockAddedNotificationMessage{ 186 | RpcBlock block = 3; 187 | } 188 | 189 | // GetPeerAddressesRequestMessage requests the list of known spectred addresses in the 190 | // current network. (mainnet, testnet, etc.) 191 | message GetPeerAddressesRequestMessage{ 192 | } 193 | 194 | message GetPeerAddressesResponseMessage{ 195 | repeated GetPeerAddressesKnownAddressMessage addresses = 1; 196 | repeated GetPeerAddressesKnownAddressMessage bannedAddresses = 2; 197 | RPCError error = 1000; 198 | } 199 | 200 | message GetPeerAddressesKnownAddressMessage { 201 | string Addr = 1; 202 | } 203 | 204 | // GetSelectedTipHashRequestMessage requests the hash of the current virtual's 205 | // selected parent. 206 | message GetSelectedTipHashRequestMessage{ 207 | } 208 | 209 | message GetSelectedTipHashResponseMessage{ 210 | string selectedTipHash = 1; 211 | RPCError error = 1000; 212 | } 213 | 214 | // GetMempoolEntryRequestMessage requests information about a specific transaction 215 | // in the mempool. 216 | message GetMempoolEntryRequestMessage{ 217 | // The transaction's TransactionID. 218 | string txId = 1; 219 | bool includeOrphanPool = 2; 220 | bool filterTransactionPool = 3; 221 | } 222 | 223 | message GetMempoolEntryResponseMessage{ 224 | MempoolEntry entry = 1; 225 | 226 | RPCError error = 1000; 227 | } 228 | 229 | // GetMempoolEntriesRequestMessage requests information about all the transactions 230 | // currently in the mempool. 231 | message GetMempoolEntriesRequestMessage{ 232 | bool includeOrphanPool = 1; 233 | bool filterTransactionPool = 2; 234 | } 235 | 236 | message GetMempoolEntriesResponseMessage{ 237 | repeated MempoolEntry entries = 1; 238 | 239 | RPCError error = 1000; 240 | } 241 | 242 | message MempoolEntry{ 243 | uint64 fee = 1; 244 | RpcTransaction transaction = 3; 245 | bool isOrphan = 4; 246 | } 247 | 248 | // GetConnectedPeerInfoRequestMessage requests information about all the p2p peers 249 | // currently connected to this spectred. 250 | message GetConnectedPeerInfoRequestMessage{ 251 | } 252 | 253 | message GetConnectedPeerInfoResponseMessage{ 254 | repeated GetConnectedPeerInfoMessage infos = 1; 255 | RPCError error = 1000; 256 | } 257 | 258 | message GetConnectedPeerInfoMessage{ 259 | string id = 1; 260 | string address = 2; 261 | 262 | // How long did the last ping/pong exchange take 263 | int64 lastPingDuration = 3; 264 | 265 | // Whether this spectred initiated the connection 266 | bool isOutbound = 6; 267 | int64 timeOffset = 7; 268 | string userAgent = 8; 269 | 270 | // The protocol version that this peer claims to support 271 | uint32 advertisedProtocolVersion = 9; 272 | 273 | // The timestamp of when this peer connected to this spectred 274 | int64 timeConnected = 10; 275 | 276 | // Whether this peer is the IBD peer (if IBD is running) 277 | bool isIbdPeer = 11; 278 | } 279 | 280 | // AddPeerRequestMessage adds a peer to spectred's outgoing connection list. 281 | // This will, in most cases, result in spectred connecting to said peer. 282 | message AddPeerRequestMessage{ 283 | string address = 1; 284 | 285 | // Whether to keep attempting to connect to this peer after disconnection 286 | bool isPermanent = 2; 287 | } 288 | 289 | message AddPeerResponseMessage{ 290 | RPCError error = 1000; 291 | } 292 | 293 | // SubmitTransactionRequestMessage submits a transaction to the mempool 294 | message SubmitTransactionRequestMessage{ 295 | RpcTransaction transaction = 1; 296 | bool allowOrphan = 2; 297 | } 298 | 299 | message SubmitTransactionResponseMessage{ 300 | // The transaction ID of the submitted transaction 301 | string transactionId = 1; 302 | 303 | RPCError error = 1000; 304 | } 305 | 306 | // NotifyVirtualSelectedParentChainChangedRequestMessage registers this connection for virtualSelectedParentChainChanged notifications. 307 | // 308 | // See: VirtualSelectedParentChainChangedNotificationMessage 309 | message NotifyVirtualSelectedParentChainChangedRequestMessage{ 310 | bool includeAcceptedTransactionIds = 1; 311 | } 312 | 313 | message NotifyVirtualSelectedParentChainChangedResponseMessage{ 314 | RPCError error = 1000; 315 | } 316 | 317 | // VirtualSelectedParentChainChangedNotificationMessage is sent whenever the DAG's selected parent 318 | // chain had changed. 319 | // 320 | // See: NotifyVirtualSelectedParentChainChangedRequestMessage 321 | message VirtualSelectedParentChainChangedNotificationMessage{ 322 | // The chain blocks that were removed, in high-to-low order 323 | repeated string removedChainBlockHashes = 1; 324 | 325 | // The chain blocks that were added, in low-to-high order 326 | repeated string addedChainBlockHashes = 3; 327 | 328 | // Will be filled only if `includeAcceptedTransactionIds = true` in the notify request. 329 | repeated AcceptedTransactionIds acceptedTransactionIds = 2; 330 | } 331 | 332 | // GetBlockRequestMessage requests information about a specific block 333 | message GetBlockRequestMessage{ 334 | // The hash of the requested block 335 | string hash = 1; 336 | 337 | // Whether to include transaction data in the response 338 | bool includeTransactions = 3; 339 | } 340 | 341 | message GetBlockResponseMessage{ 342 | RpcBlock block = 3; 343 | RPCError error = 1000; 344 | } 345 | 346 | // GetSubnetworkRequestMessage requests information about a specific subnetwork 347 | // 348 | // Currently unimplemented 349 | message GetSubnetworkRequestMessage{ 350 | string subnetworkId = 1; 351 | } 352 | 353 | message GetSubnetworkResponseMessage{ 354 | uint64 gasLimit = 1; 355 | RPCError error = 1000; 356 | } 357 | 358 | // GetVirtualSelectedParentChainFromBlockRequestMessage requests the virtual selected 359 | // parent chain from some startHash to this spectred's current virtual 360 | message GetVirtualSelectedParentChainFromBlockRequestMessage{ 361 | string startHash = 1; 362 | bool includeAcceptedTransactionIds = 2; 363 | } 364 | 365 | message AcceptedTransactionIds{ 366 | string acceptingBlockHash = 1; 367 | repeated string acceptedTransactionIds = 2; 368 | } 369 | 370 | message GetVirtualSelectedParentChainFromBlockResponseMessage{ 371 | // The chain blocks that were removed, in high-to-low order 372 | repeated string removedChainBlockHashes = 1; 373 | 374 | // The chain blocks that were added, in low-to-high order 375 | repeated string addedChainBlockHashes = 3; 376 | 377 | // The transactions accepted by each block in addedChainBlockHashes. 378 | // Will be filled only if `includeAcceptedTransactionIds = true` in the request. 379 | repeated AcceptedTransactionIds acceptedTransactionIds = 2; 380 | 381 | RPCError error = 1000; 382 | } 383 | 384 | // GetBlocksRequestMessage requests blocks between a certain block lowHash up to this 385 | // spectred's current virtual. 386 | message GetBlocksRequestMessage{ 387 | string lowHash = 1; 388 | bool includeBlocks = 2; 389 | bool includeTransactions = 3; 390 | } 391 | 392 | message GetBlocksResponseMessage{ 393 | repeated string blockHashes = 4; 394 | repeated RpcBlock blocks = 3; 395 | RPCError error = 1000; 396 | } 397 | 398 | // GetBlockCountRequestMessage requests the current number of blocks in this spectred. 399 | // Note that this number may decrease as pruning occurs. 400 | message GetBlockCountRequestMessage{ 401 | } 402 | 403 | message GetBlockCountResponseMessage{ 404 | uint64 blockCount = 1; 405 | uint64 headerCount = 2; 406 | RPCError error = 1000; 407 | } 408 | 409 | // GetBlockDagInfoRequestMessage requests general information about the current state 410 | // of this spectred's DAG. 411 | message GetBlockDagInfoRequestMessage{ 412 | } 413 | 414 | message GetBlockDagInfoResponseMessage{ 415 | string networkName = 1; 416 | uint64 blockCount = 2; 417 | uint64 headerCount = 3; 418 | repeated string tipHashes = 4; 419 | double difficulty = 5; 420 | int64 pastMedianTime = 6; 421 | repeated string virtualParentHashes = 7; 422 | string pruningPointHash = 8; 423 | uint64 virtualDaaScore = 9; 424 | RPCError error = 1000; 425 | } 426 | 427 | message ResolveFinalityConflictRequestMessage{ 428 | string finalityBlockHash = 1; 429 | } 430 | 431 | message ResolveFinalityConflictResponseMessage{ 432 | RPCError error = 1000; 433 | } 434 | 435 | message NotifyFinalityConflictsRequestMessage{ 436 | } 437 | 438 | message NotifyFinalityConflictsResponseMessage{ 439 | RPCError error = 1000; 440 | } 441 | 442 | message FinalityConflictNotificationMessage{ 443 | string violatingBlockHash = 1; 444 | } 445 | 446 | message FinalityConflictResolvedNotificationMessage{ 447 | string finalityBlockHash = 1; 448 | } 449 | 450 | // ShutDownRequestMessage shuts down this spectred. 451 | message ShutDownRequestMessage{ 452 | } 453 | 454 | message ShutDownResponseMessage{ 455 | RPCError error = 1000; 456 | } 457 | 458 | // GetHeadersRequestMessage requests headers between the given startHash and the 459 | // current virtual, up to the given limit. 460 | message GetHeadersRequestMessage{ 461 | string startHash = 1; 462 | uint64 limit = 2; 463 | bool isAscending = 3; 464 | } 465 | 466 | message GetHeadersResponseMessage{ 467 | repeated string headers = 1; 468 | RPCError error = 1000; 469 | } 470 | 471 | // NotifyUtxosChangedRequestMessage registers this connection for utxoChanged notifications 472 | // for the given addresses. 473 | // 474 | // This call is only available when this spectred was started with `--utxoindex` 475 | // 476 | // See: UtxosChangedNotificationMessage 477 | message NotifyUtxosChangedRequestMessage { 478 | repeated string addresses = 1; // Leave empty to get all updates 479 | } 480 | 481 | message NotifyUtxosChangedResponseMessage { 482 | RPCError error = 1000; 483 | } 484 | 485 | // UtxosChangedNotificationMessage is sent whenever the UTXO index had been updated. 486 | // 487 | // See: NotifyUtxosChangedRequestMessage 488 | message UtxosChangedNotificationMessage { 489 | repeated UtxosByAddressesEntry added = 1; 490 | repeated UtxosByAddressesEntry removed = 2; 491 | } 492 | 493 | message UtxosByAddressesEntry { 494 | string address = 1; 495 | RpcOutpoint outpoint = 2; 496 | RpcUtxoEntry utxoEntry = 3; 497 | } 498 | 499 | // StopNotifyingUtxosChangedRequestMessage unregisters this connection for utxoChanged notifications 500 | // for the given addresses. 501 | // 502 | // This call is only available when this spectred was started with `--utxoindex` 503 | // 504 | // See: UtxosChangedNotificationMessage 505 | message StopNotifyingUtxosChangedRequestMessage { 506 | repeated string addresses = 1; 507 | } 508 | 509 | message StopNotifyingUtxosChangedResponseMessage { 510 | RPCError error = 1000; 511 | } 512 | 513 | // GetUtxosByAddressesRequestMessage requests all current UTXOs for the given spectred addresses 514 | // 515 | // This call is only available when this spectred was started with `--utxoindex` 516 | message GetUtxosByAddressesRequestMessage { 517 | repeated string addresses = 1; 518 | } 519 | 520 | message GetUtxosByAddressesResponseMessage { 521 | repeated UtxosByAddressesEntry entries = 1; 522 | 523 | RPCError error = 1000; 524 | } 525 | 526 | // GetBalanceByAddressRequest returns the total balance in unspent transactions towards a given address 527 | // 528 | // This call is only available when this spectred was started with `--utxoindex` 529 | message GetBalanceByAddressRequestMessage { 530 | string address = 1; 531 | } 532 | 533 | message GetBalanceByAddressResponseMessage { 534 | uint64 balance = 1; 535 | 536 | RPCError error = 1000; 537 | } 538 | 539 | message GetBalancesByAddressesRequestMessage { 540 | repeated string addresses = 1; 541 | } 542 | 543 | message BalancesByAddressEntry{ 544 | string address = 1; 545 | uint64 balance = 2; 546 | 547 | RPCError error = 1000; 548 | } 549 | 550 | message GetBalancesByAddressesResponseMessage { 551 | repeated BalancesByAddressEntry entries = 1; 552 | 553 | RPCError error = 1000; 554 | } 555 | 556 | // GetVirtualSelectedParentBlueScoreRequestMessage requests the blue score of the current selected parent 557 | // of the virtual block. 558 | message GetVirtualSelectedParentBlueScoreRequestMessage { 559 | } 560 | 561 | message GetVirtualSelectedParentBlueScoreResponseMessage { 562 | uint64 blueScore = 1; 563 | 564 | RPCError error = 1000; 565 | } 566 | 567 | // NotifyVirtualSelectedParentBlueScoreChangedRequestMessage registers this connection for 568 | // virtualSelectedParentBlueScoreChanged notifications. 569 | // 570 | // See: VirtualSelectedParentBlueScoreChangedNotificationMessage 571 | message NotifyVirtualSelectedParentBlueScoreChangedRequestMessage { 572 | } 573 | 574 | message NotifyVirtualSelectedParentBlueScoreChangedResponseMessage { 575 | RPCError error = 1000; 576 | } 577 | 578 | // VirtualSelectedParentBlueScoreChangedNotificationMessage is sent whenever the blue score 579 | // of the virtual's selected parent changes. 580 | // 581 | // See NotifyVirtualSelectedParentBlueScoreChangedRequestMessage 582 | message VirtualSelectedParentBlueScoreChangedNotificationMessage { 583 | uint64 virtualSelectedParentBlueScore = 1; 584 | } 585 | 586 | // NotifyVirtualDaaScoreChangedRequestMessage registers this connection for 587 | // virtualDaaScoreChanged notifications. 588 | // 589 | // See: VirtualDaaScoreChangedNotificationMessage 590 | message NotifyVirtualDaaScoreChangedRequestMessage { 591 | } 592 | 593 | message NotifyVirtualDaaScoreChangedResponseMessage { 594 | RPCError error = 1000; 595 | } 596 | 597 | // VirtualDaaScoreChangedNotificationMessage is sent whenever the DAA score 598 | // of the virtual changes. 599 | // 600 | // See NotifyVirtualDaaScoreChangedRequestMessage 601 | message VirtualDaaScoreChangedNotificationMessage { 602 | uint64 virtualDaaScore = 1; 603 | } 604 | 605 | // NotifyPruningPointUTXOSetOverrideRequestMessage registers this connection for 606 | // pruning point UTXO set override notifications. 607 | // 608 | // This call is only available when this spectred was started with `--utxoindex` 609 | // 610 | // See: NotifyPruningPointUTXOSetOverrideResponseMessage 611 | message NotifyPruningPointUTXOSetOverrideRequestMessage { 612 | } 613 | 614 | 615 | message NotifyPruningPointUTXOSetOverrideResponseMessage { 616 | RPCError error = 1000; 617 | } 618 | 619 | // PruningPointUTXOSetOverrideNotificationMessage is sent whenever the UTXO index 620 | // resets due to pruning point change via IBD. 621 | // 622 | // See NotifyPruningPointUTXOSetOverrideRequestMessage 623 | message PruningPointUTXOSetOverrideNotificationMessage { 624 | } 625 | 626 | // StopNotifyingPruningPointUTXOSetOverrideRequestMessage unregisters this connection for 627 | // pruning point UTXO set override notifications. 628 | // 629 | // This call is only available when this spectred was started with `--utxoindex` 630 | // 631 | // See: PruningPointUTXOSetOverrideNotificationMessage 632 | message StopNotifyingPruningPointUTXOSetOverrideRequestMessage { 633 | } 634 | 635 | message StopNotifyingPruningPointUTXOSetOverrideResponseMessage { 636 | RPCError error = 1000; 637 | } 638 | 639 | // BanRequestMessage bans the given ip. 640 | message BanRequestMessage{ 641 | string ip = 1; 642 | } 643 | 644 | message BanResponseMessage{ 645 | RPCError error = 1000; 646 | } 647 | 648 | // UnbanRequestMessage unbans the given ip. 649 | message UnbanRequestMessage{ 650 | string ip = 1; 651 | } 652 | 653 | message UnbanResponseMessage{ 654 | RPCError error = 1000; 655 | } 656 | 657 | // GetInfoRequestMessage returns info about the node. 658 | message GetInfoRequestMessage{ 659 | } 660 | 661 | message GetInfoResponseMessage{ 662 | string p2pId = 1; 663 | uint64 mempoolSize = 2; 664 | string serverVersion = 3; 665 | bool isUtxoIndexed = 4; 666 | bool isSynced = 5; 667 | RPCError error = 1000; 668 | } 669 | 670 | message EstimateNetworkHashesPerSecondRequestMessage{ 671 | uint32 windowSize = 1; 672 | string startHash = 2; 673 | } 674 | 675 | message EstimateNetworkHashesPerSecondResponseMessage{ 676 | uint64 networkHashesPerSecond = 1; 677 | RPCError error = 1000; 678 | } 679 | 680 | // NotifyNewBlockTemplateRequestMessage registers this connection for 681 | // NewBlockTemplate notifications. 682 | // 683 | // See: NewBlockTemplateNotificationMessage 684 | message NotifyNewBlockTemplateRequestMessage { 685 | } 686 | 687 | message NotifyNewBlockTemplateResponseMessage { 688 | RPCError error = 1000; 689 | } 690 | 691 | // NewBlockTemplateNotificationMessage is sent whenever a new updated block template is 692 | // available for miners. 693 | // 694 | // See NotifyNewBlockTemplateRequestMessage 695 | message NewBlockTemplateNotificationMessage { 696 | } 697 | 698 | message MempoolEntryByAddress{ 699 | string address = 1; 700 | repeated MempoolEntry sending = 2; 701 | repeated MempoolEntry receiving = 3; 702 | } 703 | 704 | message GetMempoolEntriesByAddressesRequestMessage{ 705 | repeated string addresses = 1; 706 | bool includeOrphanPool = 2; 707 | bool filterTransactionPool = 3; 708 | } 709 | 710 | message GetMempoolEntriesByAddressesResponseMessage{ 711 | repeated MempoolEntryByAddress entries = 1; 712 | 713 | RPCError error = 1000; 714 | } 715 | 716 | message GetCoinSupplyRequestMessage{ 717 | } 718 | 719 | message GetCoinSupplyResponseMessage{ 720 | uint64 maxSompi = 1; // note: this is a hard coded maxSupply, actual maxSupply is expected to deviate by upto -5%, but cannot be measured exactly. 721 | uint64 circulatingSompi = 2; 722 | 723 | RPCError error = 1000; 724 | } 725 | -------------------------------------------------------------------------------- /src/asm/keccakf1600_x86-64-elf.s: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/dot-asm/cryptogams/blob/master/x86_64/keccak1600-x86_64.pl 2 | 3 | .text 4 | 5 | .type __KeccakF1600,@function 6 | .align 32 7 | __KeccakF1600: 8 | .cfi_startproc 9 | .byte 0xf3,0x0f,0x1e,0xfa 10 | 11 | movq 60(%rdi),%rax 12 | movq 68(%rdi),%rbx 13 | movq 76(%rdi),%rcx 14 | movq 84(%rdi),%rdx 15 | movq 92(%rdi),%rbp 16 | jmp .Loop 17 | 18 | .align 32 19 | .Loop: 20 | movq -100(%rdi),%r8 21 | movq -52(%rdi),%r9 22 | movq -4(%rdi),%r10 23 | movq 44(%rdi),%r11 24 | 25 | xorq -84(%rdi),%rcx 26 | xorq -76(%rdi),%rdx 27 | xorq %r8,%rax 28 | xorq -92(%rdi),%rbx 29 | xorq -44(%rdi),%rcx 30 | xorq -60(%rdi),%rax 31 | movq %rbp,%r12 32 | xorq -68(%rdi),%rbp 33 | 34 | xorq %r10,%rcx 35 | xorq -20(%rdi),%rax 36 | xorq -36(%rdi),%rdx 37 | xorq %r9,%rbx 38 | xorq -28(%rdi),%rbp 39 | 40 | xorq 36(%rdi),%rcx 41 | xorq 20(%rdi),%rax 42 | xorq 4(%rdi),%rdx 43 | xorq -12(%rdi),%rbx 44 | xorq 12(%rdi),%rbp 45 | 46 | movq %rcx,%r13 47 | rolq $1,%rcx 48 | xorq %rax,%rcx 49 | xorq %r11,%rdx 50 | 51 | rolq $1,%rax 52 | xorq %rdx,%rax 53 | xorq 28(%rdi),%rbx 54 | 55 | rolq $1,%rdx 56 | xorq %rbx,%rdx 57 | xorq 52(%rdi),%rbp 58 | 59 | rolq $1,%rbx 60 | xorq %rbp,%rbx 61 | 62 | rolq $1,%rbp 63 | xorq %r13,%rbp 64 | xorq %rcx,%r9 65 | xorq %rdx,%r10 66 | rolq $44,%r9 67 | xorq %rbp,%r11 68 | xorq %rax,%r12 69 | rolq $43,%r10 70 | xorq %rbx,%r8 71 | movq %r9,%r13 72 | rolq $21,%r11 73 | orq %r10,%r9 74 | xorq %r8,%r9 75 | rolq $14,%r12 76 | 77 | xorq (%r15),%r9 78 | leaq 8(%r15),%r15 79 | 80 | movq %r12,%r14 81 | andq %r11,%r12 82 | movq %r9,-100(%rsi) 83 | xorq %r10,%r12 84 | notq %r10 85 | movq %r12,-84(%rsi) 86 | 87 | orq %r11,%r10 88 | movq 76(%rdi),%r12 89 | xorq %r13,%r10 90 | movq %r10,-92(%rsi) 91 | 92 | andq %r8,%r13 93 | movq -28(%rdi),%r9 94 | xorq %r14,%r13 95 | movq -20(%rdi),%r10 96 | movq %r13,-68(%rsi) 97 | 98 | orq %r8,%r14 99 | movq -76(%rdi),%r8 100 | xorq %r11,%r14 101 | movq 28(%rdi),%r11 102 | movq %r14,-76(%rsi) 103 | 104 | 105 | xorq %rbp,%r8 106 | xorq %rdx,%r12 107 | rolq $28,%r8 108 | xorq %rcx,%r11 109 | xorq %rax,%r9 110 | rolq $61,%r12 111 | rolq $45,%r11 112 | xorq %rbx,%r10 113 | rolq $20,%r9 114 | movq %r8,%r13 115 | orq %r12,%r8 116 | rolq $3,%r10 117 | 118 | xorq %r11,%r8 119 | movq %r8,-36(%rsi) 120 | 121 | movq %r9,%r14 122 | andq %r13,%r9 123 | movq -92(%rdi),%r8 124 | xorq %r12,%r9 125 | notq %r12 126 | movq %r9,-28(%rsi) 127 | 128 | orq %r11,%r12 129 | movq -44(%rdi),%r9 130 | xorq %r10,%r12 131 | movq %r12,-44(%rsi) 132 | 133 | andq %r10,%r11 134 | movq 60(%rdi),%r12 135 | xorq %r14,%r11 136 | movq %r11,-52(%rsi) 137 | 138 | orq %r10,%r14 139 | movq 4(%rdi),%r10 140 | xorq %r13,%r14 141 | movq 52(%rdi),%r11 142 | movq %r14,-60(%rsi) 143 | 144 | 145 | xorq %rbp,%r10 146 | xorq %rax,%r11 147 | rolq $25,%r10 148 | xorq %rdx,%r9 149 | rolq $8,%r11 150 | xorq %rbx,%r12 151 | rolq $6,%r9 152 | xorq %rcx,%r8 153 | rolq $18,%r12 154 | movq %r10,%r13 155 | andq %r11,%r10 156 | rolq $1,%r8 157 | 158 | notq %r11 159 | xorq %r9,%r10 160 | movq %r10,-12(%rsi) 161 | 162 | movq %r12,%r14 163 | andq %r11,%r12 164 | movq -12(%rdi),%r10 165 | xorq %r13,%r12 166 | movq %r12,-4(%rsi) 167 | 168 | orq %r9,%r13 169 | movq 84(%rdi),%r12 170 | xorq %r8,%r13 171 | movq %r13,-20(%rsi) 172 | 173 | andq %r8,%r9 174 | xorq %r14,%r9 175 | movq %r9,12(%rsi) 176 | 177 | orq %r8,%r14 178 | movq -60(%rdi),%r9 179 | xorq %r11,%r14 180 | movq 36(%rdi),%r11 181 | movq %r14,4(%rsi) 182 | 183 | 184 | movq -68(%rdi),%r8 185 | 186 | xorq %rcx,%r10 187 | xorq %rdx,%r11 188 | rolq $10,%r10 189 | xorq %rbx,%r9 190 | rolq $15,%r11 191 | xorq %rbp,%r12 192 | rolq $36,%r9 193 | xorq %rax,%r8 194 | rolq $56,%r12 195 | movq %r10,%r13 196 | orq %r11,%r10 197 | rolq $27,%r8 198 | 199 | notq %r11 200 | xorq %r9,%r10 201 | movq %r10,28(%rsi) 202 | 203 | movq %r12,%r14 204 | orq %r11,%r12 205 | xorq %r13,%r12 206 | movq %r12,36(%rsi) 207 | 208 | andq %r9,%r13 209 | xorq %r8,%r13 210 | movq %r13,20(%rsi) 211 | 212 | orq %r8,%r9 213 | xorq %r14,%r9 214 | movq %r9,52(%rsi) 215 | 216 | andq %r14,%r8 217 | xorq %r11,%r8 218 | movq %r8,44(%rsi) 219 | 220 | 221 | xorq -84(%rdi),%rdx 222 | xorq -36(%rdi),%rbp 223 | rolq $62,%rdx 224 | xorq 68(%rdi),%rcx 225 | rolq $55,%rbp 226 | xorq 12(%rdi),%rax 227 | rolq $2,%rcx 228 | xorq 20(%rdi),%rbx 229 | xchgq %rsi,%rdi 230 | rolq $39,%rax 231 | rolq $41,%rbx 232 | movq %rdx,%r13 233 | andq %rbp,%rdx 234 | notq %rbp 235 | xorq %rcx,%rdx 236 | movq %rdx,92(%rdi) 237 | 238 | movq %rax,%r14 239 | andq %rbp,%rax 240 | xorq %r13,%rax 241 | movq %rax,60(%rdi) 242 | 243 | orq %rcx,%r13 244 | xorq %rbx,%r13 245 | movq %r13,84(%rdi) 246 | 247 | andq %rbx,%rcx 248 | xorq %r14,%rcx 249 | movq %rcx,76(%rdi) 250 | 251 | orq %r14,%rbx 252 | xorq %rbp,%rbx 253 | movq %rbx,68(%rdi) 254 | 255 | movq %rdx,%rbp 256 | movq %r13,%rdx 257 | 258 | testq $255,%r15 259 | jnz .Loop 260 | 261 | leaq -192(%r15),%r15 262 | .byte 0xf3,0xc3 263 | .cfi_endproc 264 | .size __KeccakF1600,.-__KeccakF1600 265 | 266 | .globl KeccakF1600 267 | .type KeccakF1600,@function 268 | .align 32 269 | KeccakF1600: 270 | .cfi_startproc 271 | .byte 0xf3,0x0f,0x1e,0xfa 272 | 273 | 274 | pushq %rbx 275 | .cfi_adjust_cfa_offset 8 276 | .cfi_offset %rbx,-16 277 | pushq %rbp 278 | .cfi_adjust_cfa_offset 8 279 | .cfi_offset %rbp,-24 280 | pushq %r12 281 | .cfi_adjust_cfa_offset 8 282 | .cfi_offset %r12,-32 283 | pushq %r13 284 | .cfi_adjust_cfa_offset 8 285 | .cfi_offset %r13,-40 286 | pushq %r14 287 | .cfi_adjust_cfa_offset 8 288 | .cfi_offset %r14,-48 289 | pushq %r15 290 | .cfi_adjust_cfa_offset 8 291 | .cfi_offset %r15,-56 292 | 293 | leaq 100(%rdi),%rdi 294 | subq $200,%rsp 295 | .cfi_adjust_cfa_offset 200 296 | 297 | 298 | notq -92(%rdi) 299 | notq -84(%rdi) 300 | notq -36(%rdi) 301 | notq -4(%rdi) 302 | notq 36(%rdi) 303 | notq 60(%rdi) 304 | 305 | leaq iotas(%rip),%r15 306 | leaq 100(%rsp),%rsi 307 | 308 | call __KeccakF1600 309 | 310 | notq -92(%rdi) 311 | notq -84(%rdi) 312 | notq -36(%rdi) 313 | notq -4(%rdi) 314 | notq 36(%rdi) 315 | notq 60(%rdi) 316 | leaq -100(%rdi),%rdi 317 | 318 | leaq 248(%rsp),%r11 319 | .cfi_def_cfa %r11,8 320 | movq -48(%r11),%r15 321 | movq -40(%r11),%r14 322 | movq -32(%r11),%r13 323 | movq -24(%r11),%r12 324 | movq -16(%r11),%rbp 325 | movq -8(%r11),%rbx 326 | leaq (%r11),%rsp 327 | .cfi_restore %r12 328 | .cfi_restore %r13 329 | .cfi_restore %r14 330 | .cfi_restore %r15 331 | .cfi_restore %rbp 332 | .cfi_restore %rbx 333 | .byte 0xf3,0xc3 334 | .cfi_endproc 335 | .size KeccakF1600,.-KeccakF1600 336 | .globl SHA3_absorb 337 | .type SHA3_absorb,@function 338 | .align 32 339 | SHA3_absorb: 340 | .cfi_startproc 341 | .byte 0xf3,0x0f,0x1e,0xfa 342 | 343 | 344 | pushq %rbx 345 | .cfi_adjust_cfa_offset 8 346 | .cfi_offset %rbx,-16 347 | pushq %rbp 348 | .cfi_adjust_cfa_offset 8 349 | .cfi_offset %rbp,-24 350 | pushq %r12 351 | .cfi_adjust_cfa_offset 8 352 | .cfi_offset %r12,-32 353 | pushq %r13 354 | .cfi_adjust_cfa_offset 8 355 | .cfi_offset %r13,-40 356 | pushq %r14 357 | .cfi_adjust_cfa_offset 8 358 | .cfi_offset %r14,-48 359 | pushq %r15 360 | .cfi_adjust_cfa_offset 8 361 | .cfi_offset %r15,-56 362 | 363 | leaq 100(%rdi),%rdi 364 | subq $232,%rsp 365 | .cfi_adjust_cfa_offset 232 366 | 367 | 368 | movq %rsi,%r9 369 | leaq 100(%rsp),%rsi 370 | 371 | notq -92(%rdi) 372 | notq -84(%rdi) 373 | notq -36(%rdi) 374 | notq -4(%rdi) 375 | notq 36(%rdi) 376 | notq 60(%rdi) 377 | leaq iotas(%rip),%r15 378 | 379 | movq %rcx,216-100(%rsi) 380 | 381 | .Loop_absorb: 382 | cmpq %rcx,%rdx 383 | jc .Ldone_absorb 384 | 385 | shrq $3,%rcx 386 | leaq -100(%rdi),%r8 387 | 388 | .Lblock_absorb: 389 | movq (%r9),%rax 390 | leaq 8(%r9),%r9 391 | xorq (%r8),%rax 392 | leaq 8(%r8),%r8 393 | subq $8,%rdx 394 | movq %rax,-8(%r8) 395 | subq $1,%rcx 396 | jnz .Lblock_absorb 397 | 398 | movq %r9,200-100(%rsi) 399 | movq %rdx,208-100(%rsi) 400 | call __KeccakF1600 401 | movq 200-100(%rsi),%r9 402 | movq 208-100(%rsi),%rdx 403 | movq 216-100(%rsi),%rcx 404 | jmp .Loop_absorb 405 | 406 | .align 32 407 | .Ldone_absorb: 408 | movq %rdx,%rax 409 | 410 | notq -92(%rdi) 411 | notq -84(%rdi) 412 | notq -36(%rdi) 413 | notq -4(%rdi) 414 | notq 36(%rdi) 415 | notq 60(%rdi) 416 | 417 | leaq 280(%rsp),%r11 418 | .cfi_def_cfa %r11,8 419 | movq -48(%r11),%r15 420 | movq -40(%r11),%r14 421 | movq -32(%r11),%r13 422 | movq -24(%r11),%r12 423 | movq -16(%r11),%rbp 424 | movq -8(%r11),%rbx 425 | leaq (%r11),%rsp 426 | .cfi_restore %r12 427 | .cfi_restore %r13 428 | .cfi_restore %r14 429 | .cfi_restore %r15 430 | .cfi_restore %rbp 431 | .cfi_restore %rbx 432 | .byte 0xf3,0xc3 433 | .cfi_endproc 434 | .size SHA3_absorb,.-SHA3_absorb 435 | .globl SHA3_squeeze 436 | .type SHA3_squeeze,@function 437 | .align 32 438 | SHA3_squeeze: 439 | .cfi_startproc 440 | .byte 0xf3,0x0f,0x1e,0xfa 441 | 442 | 443 | pushq %r12 444 | .cfi_adjust_cfa_offset 8 445 | .cfi_offset %r12,-16 446 | pushq %r13 447 | .cfi_adjust_cfa_offset 8 448 | .cfi_offset %r13,-24 449 | pushq %r14 450 | .cfi_adjust_cfa_offset 8 451 | .cfi_offset %r14,-32 452 | subq $32,%rsp 453 | .cfi_adjust_cfa_offset 32 454 | 455 | 456 | shrq $3,%rcx 457 | movq %rdi,%r8 458 | movq %rsi,%r12 459 | movq %rdx,%r13 460 | movq %rcx,%r14 461 | jmp .Loop_squeeze 462 | 463 | .align 32 464 | .Loop_squeeze: 465 | cmpq $8,%r13 466 | jb .Ltail_squeeze 467 | 468 | movq (%r8),%rax 469 | leaq 8(%r8),%r8 470 | movq %rax,(%r12) 471 | leaq 8(%r12),%r12 472 | subq $8,%r13 473 | jz .Ldone_squeeze 474 | 475 | subq $1,%rcx 476 | jnz .Loop_squeeze 477 | 478 | movq %rdi,%rcx 479 | call KeccakF1600 480 | movq %rdi,%r8 481 | movq %r14,%rcx 482 | jmp .Loop_squeeze 483 | 484 | .Ltail_squeeze: 485 | movq %r8,%rsi 486 | movq %r12,%rdi 487 | movq %r13,%rcx 488 | .byte 0xf3,0xa4 489 | 490 | .Ldone_squeeze: 491 | movq 32(%rsp),%r14 492 | movq 40(%rsp),%r13 493 | movq 48(%rsp),%r12 494 | addq $56,%rsp 495 | .cfi_adjust_cfa_offset -56 496 | .cfi_restore %r12 497 | .cfi_restore %r13 498 | .cfi_restore %r14 499 | .byte 0xf3,0xc3 500 | .cfi_endproc 501 | .size SHA3_squeeze,.-SHA3_squeeze 502 | .align 256 503 | .quad 0,0,0,0,0,0,0,0 504 | .type iotas,@object 505 | iotas: 506 | .quad 0x0000000000000001 507 | .quad 0x0000000000008082 508 | .quad 0x800000000000808a 509 | .quad 0x8000000080008000 510 | .quad 0x000000000000808b 511 | .quad 0x0000000080000001 512 | .quad 0x8000000080008081 513 | .quad 0x8000000000008009 514 | .quad 0x000000000000008a 515 | .quad 0x0000000000000088 516 | .quad 0x0000000080008009 517 | .quad 0x000000008000000a 518 | .quad 0x000000008000808b 519 | .quad 0x800000000000008b 520 | .quad 0x8000000000008089 521 | .quad 0x8000000000008003 522 | .quad 0x8000000000008002 523 | .quad 0x8000000000000080 524 | .quad 0x000000000000800a 525 | .quad 0x800000008000000a 526 | .quad 0x8000000080008081 527 | .quad 0x8000000000008080 528 | .quad 0x0000000080000001 529 | .quad 0x8000000080008008 530 | .size iotas,.-iotas 531 | .byte 75,101,99,99,97,107,45,49,54,48,48,32,97,98,115,111,114,98,32,97,110,100,32,115,113,117,101,101,122,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 532 | 533 | .section .note.gnu.property,"a",@note 534 | .long 4,2f-1f,5 535 | .byte 0x47,0x4E,0x55,0 536 | 1: .long 0xc0000002,4,3 537 | .align 8 538 | 2: 539 | -------------------------------------------------------------------------------- /src/asm/keccakf1600_x86-64-mingw64.s: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/dot-asm/cryptogams/blob/master/x86_64/keccak1600-x86_64.pl 2 | 3 | .text 4 | 5 | .def __KeccakF1600; .scl 3; .type 32; .endef 6 | .p2align 5 7 | __KeccakF1600: 8 | .byte 0xf3,0x0f,0x1e,0xfa 9 | 10 | movq 60(%rdi),%rax 11 | movq 68(%rdi),%rbx 12 | movq 76(%rdi),%rcx 13 | movq 84(%rdi),%rdx 14 | movq 92(%rdi),%rbp 15 | jmp .Loop 16 | 17 | .p2align 5 18 | .Loop: 19 | movq -100(%rdi),%r8 20 | movq -52(%rdi),%r9 21 | movq -4(%rdi),%r10 22 | movq 44(%rdi),%r11 23 | 24 | xorq -84(%rdi),%rcx 25 | xorq -76(%rdi),%rdx 26 | xorq %r8,%rax 27 | xorq -92(%rdi),%rbx 28 | xorq -44(%rdi),%rcx 29 | xorq -60(%rdi),%rax 30 | movq %rbp,%r12 31 | xorq -68(%rdi),%rbp 32 | 33 | xorq %r10,%rcx 34 | xorq -20(%rdi),%rax 35 | xorq -36(%rdi),%rdx 36 | xorq %r9,%rbx 37 | xorq -28(%rdi),%rbp 38 | 39 | xorq 36(%rdi),%rcx 40 | xorq 20(%rdi),%rax 41 | xorq 4(%rdi),%rdx 42 | xorq -12(%rdi),%rbx 43 | xorq 12(%rdi),%rbp 44 | 45 | movq %rcx,%r13 46 | rolq $1,%rcx 47 | xorq %rax,%rcx 48 | xorq %r11,%rdx 49 | 50 | rolq $1,%rax 51 | xorq %rdx,%rax 52 | xorq 28(%rdi),%rbx 53 | 54 | rolq $1,%rdx 55 | xorq %rbx,%rdx 56 | xorq 52(%rdi),%rbp 57 | 58 | rolq $1,%rbx 59 | xorq %rbp,%rbx 60 | 61 | rolq $1,%rbp 62 | xorq %r13,%rbp 63 | xorq %rcx,%r9 64 | xorq %rdx,%r10 65 | rolq $44,%r9 66 | xorq %rbp,%r11 67 | xorq %rax,%r12 68 | rolq $43,%r10 69 | xorq %rbx,%r8 70 | movq %r9,%r13 71 | rolq $21,%r11 72 | orq %r10,%r9 73 | xorq %r8,%r9 74 | rolq $14,%r12 75 | 76 | xorq (%r15),%r9 77 | leaq 8(%r15),%r15 78 | 79 | movq %r12,%r14 80 | andq %r11,%r12 81 | movq %r9,-100(%rsi) 82 | xorq %r10,%r12 83 | notq %r10 84 | movq %r12,-84(%rsi) 85 | 86 | orq %r11,%r10 87 | movq 76(%rdi),%r12 88 | xorq %r13,%r10 89 | movq %r10,-92(%rsi) 90 | 91 | andq %r8,%r13 92 | movq -28(%rdi),%r9 93 | xorq %r14,%r13 94 | movq -20(%rdi),%r10 95 | movq %r13,-68(%rsi) 96 | 97 | orq %r8,%r14 98 | movq -76(%rdi),%r8 99 | xorq %r11,%r14 100 | movq 28(%rdi),%r11 101 | movq %r14,-76(%rsi) 102 | 103 | 104 | xorq %rbp,%r8 105 | xorq %rdx,%r12 106 | rolq $28,%r8 107 | xorq %rcx,%r11 108 | xorq %rax,%r9 109 | rolq $61,%r12 110 | rolq $45,%r11 111 | xorq %rbx,%r10 112 | rolq $20,%r9 113 | movq %r8,%r13 114 | orq %r12,%r8 115 | rolq $3,%r10 116 | 117 | xorq %r11,%r8 118 | movq %r8,-36(%rsi) 119 | 120 | movq %r9,%r14 121 | andq %r13,%r9 122 | movq -92(%rdi),%r8 123 | xorq %r12,%r9 124 | notq %r12 125 | movq %r9,-28(%rsi) 126 | 127 | orq %r11,%r12 128 | movq -44(%rdi),%r9 129 | xorq %r10,%r12 130 | movq %r12,-44(%rsi) 131 | 132 | andq %r10,%r11 133 | movq 60(%rdi),%r12 134 | xorq %r14,%r11 135 | movq %r11,-52(%rsi) 136 | 137 | orq %r10,%r14 138 | movq 4(%rdi),%r10 139 | xorq %r13,%r14 140 | movq 52(%rdi),%r11 141 | movq %r14,-60(%rsi) 142 | 143 | 144 | xorq %rbp,%r10 145 | xorq %rax,%r11 146 | rolq $25,%r10 147 | xorq %rdx,%r9 148 | rolq $8,%r11 149 | xorq %rbx,%r12 150 | rolq $6,%r9 151 | xorq %rcx,%r8 152 | rolq $18,%r12 153 | movq %r10,%r13 154 | andq %r11,%r10 155 | rolq $1,%r8 156 | 157 | notq %r11 158 | xorq %r9,%r10 159 | movq %r10,-12(%rsi) 160 | 161 | movq %r12,%r14 162 | andq %r11,%r12 163 | movq -12(%rdi),%r10 164 | xorq %r13,%r12 165 | movq %r12,-4(%rsi) 166 | 167 | orq %r9,%r13 168 | movq 84(%rdi),%r12 169 | xorq %r8,%r13 170 | movq %r13,-20(%rsi) 171 | 172 | andq %r8,%r9 173 | xorq %r14,%r9 174 | movq %r9,12(%rsi) 175 | 176 | orq %r8,%r14 177 | movq -60(%rdi),%r9 178 | xorq %r11,%r14 179 | movq 36(%rdi),%r11 180 | movq %r14,4(%rsi) 181 | 182 | 183 | movq -68(%rdi),%r8 184 | 185 | xorq %rcx,%r10 186 | xorq %rdx,%r11 187 | rolq $10,%r10 188 | xorq %rbx,%r9 189 | rolq $15,%r11 190 | xorq %rbp,%r12 191 | rolq $36,%r9 192 | xorq %rax,%r8 193 | rolq $56,%r12 194 | movq %r10,%r13 195 | orq %r11,%r10 196 | rolq $27,%r8 197 | 198 | notq %r11 199 | xorq %r9,%r10 200 | movq %r10,28(%rsi) 201 | 202 | movq %r12,%r14 203 | orq %r11,%r12 204 | xorq %r13,%r12 205 | movq %r12,36(%rsi) 206 | 207 | andq %r9,%r13 208 | xorq %r8,%r13 209 | movq %r13,20(%rsi) 210 | 211 | orq %r8,%r9 212 | xorq %r14,%r9 213 | movq %r9,52(%rsi) 214 | 215 | andq %r14,%r8 216 | xorq %r11,%r8 217 | movq %r8,44(%rsi) 218 | 219 | 220 | xorq -84(%rdi),%rdx 221 | xorq -36(%rdi),%rbp 222 | rolq $62,%rdx 223 | xorq 68(%rdi),%rcx 224 | rolq $55,%rbp 225 | xorq 12(%rdi),%rax 226 | rolq $2,%rcx 227 | xorq 20(%rdi),%rbx 228 | xchgq %rsi,%rdi 229 | rolq $39,%rax 230 | rolq $41,%rbx 231 | movq %rdx,%r13 232 | andq %rbp,%rdx 233 | notq %rbp 234 | xorq %rcx,%rdx 235 | movq %rdx,92(%rdi) 236 | 237 | movq %rax,%r14 238 | andq %rbp,%rax 239 | xorq %r13,%rax 240 | movq %rax,60(%rdi) 241 | 242 | orq %rcx,%r13 243 | xorq %rbx,%r13 244 | movq %r13,84(%rdi) 245 | 246 | andq %rbx,%rcx 247 | xorq %r14,%rcx 248 | movq %rcx,76(%rdi) 249 | 250 | orq %r14,%rbx 251 | xorq %rbp,%rbx 252 | movq %rbx,68(%rdi) 253 | 254 | movq %rdx,%rbp 255 | movq %r13,%rdx 256 | 257 | testq $255,%r15 258 | jnz .Loop 259 | 260 | leaq -192(%r15),%r15 261 | .byte 0xf3,0xc3 262 | 263 | 264 | .globl KeccakF1600 265 | .def KeccakF1600; .scl 2; .type 32; .endef 266 | .p2align 5 267 | KeccakF1600: 268 | .byte 0xf3,0x0f,0x1e,0xfa 269 | movq %rdi,8(%rsp) 270 | movq %rsi,16(%rsp) 271 | movq %rsp,%r11 272 | .LSEH_begin_KeccakF1600: 273 | 274 | 275 | movq %rcx,%rdi 276 | pushq %rbx 277 | 278 | pushq %rbp 279 | 280 | pushq %r12 281 | 282 | pushq %r13 283 | 284 | pushq %r14 285 | 286 | pushq %r15 287 | 288 | 289 | leaq 100(%rdi),%rdi 290 | subq $200,%rsp 291 | 292 | .LSEH_body_KeccakF1600: 293 | 294 | 295 | notq -92(%rdi) 296 | notq -84(%rdi) 297 | notq -36(%rdi) 298 | notq -4(%rdi) 299 | notq 36(%rdi) 300 | notq 60(%rdi) 301 | 302 | leaq iotas(%rip),%r15 303 | leaq 100(%rsp),%rsi 304 | 305 | call __KeccakF1600 306 | 307 | notq -92(%rdi) 308 | notq -84(%rdi) 309 | notq -36(%rdi) 310 | notq -4(%rdi) 311 | notq 36(%rdi) 312 | notq 60(%rdi) 313 | leaq -100(%rdi),%rdi 314 | 315 | leaq 248(%rsp),%r11 316 | 317 | movq -48(%r11),%r15 318 | movq -40(%r11),%r14 319 | movq -32(%r11),%r13 320 | movq -24(%r11),%r12 321 | movq -16(%r11),%rbp 322 | movq -8(%r11),%rbx 323 | leaq (%r11),%rsp 324 | .LSEH_epilogue_KeccakF1600: 325 | mov 8(%r11),%rdi 326 | mov 16(%r11),%rsi 327 | 328 | .byte 0xf3,0xc3 329 | 330 | .LSEH_end_KeccakF1600: 331 | .globl SHA3_absorb 332 | .def SHA3_absorb; .scl 2; .type 32; .endef 333 | .p2align 5 334 | SHA3_absorb: 335 | .byte 0xf3,0x0f,0x1e,0xfa 336 | movq %rdi,8(%rsp) 337 | movq %rsi,16(%rsp) 338 | movq %rsp,%r11 339 | .LSEH_begin_SHA3_absorb: 340 | 341 | 342 | movq %rcx,%rdi 343 | movq %rdx,%rsi 344 | movq %r8,%rdx 345 | movq %r9,%rcx 346 | pushq %rbx 347 | 348 | pushq %rbp 349 | 350 | pushq %r12 351 | 352 | pushq %r13 353 | 354 | pushq %r14 355 | 356 | pushq %r15 357 | 358 | 359 | leaq 100(%rdi),%rdi 360 | subq $232,%rsp 361 | 362 | .LSEH_body_SHA3_absorb: 363 | 364 | 365 | movq %rsi,%r9 366 | leaq 100(%rsp),%rsi 367 | 368 | notq -92(%rdi) 369 | notq -84(%rdi) 370 | notq -36(%rdi) 371 | notq -4(%rdi) 372 | notq 36(%rdi) 373 | notq 60(%rdi) 374 | leaq iotas(%rip),%r15 375 | 376 | movq %rcx,216-100(%rsi) 377 | 378 | .Loop_absorb: 379 | cmpq %rcx,%rdx 380 | jc .Ldone_absorb 381 | 382 | shrq $3,%rcx 383 | leaq -100(%rdi),%r8 384 | 385 | .Lblock_absorb: 386 | movq (%r9),%rax 387 | leaq 8(%r9),%r9 388 | xorq (%r8),%rax 389 | leaq 8(%r8),%r8 390 | subq $8,%rdx 391 | movq %rax,-8(%r8) 392 | subq $1,%rcx 393 | jnz .Lblock_absorb 394 | 395 | movq %r9,200-100(%rsi) 396 | movq %rdx,208-100(%rsi) 397 | call __KeccakF1600 398 | movq 200-100(%rsi),%r9 399 | movq 208-100(%rsi),%rdx 400 | movq 216-100(%rsi),%rcx 401 | jmp .Loop_absorb 402 | 403 | .p2align 5 404 | .Ldone_absorb: 405 | movq %rdx,%rax 406 | 407 | notq -92(%rdi) 408 | notq -84(%rdi) 409 | notq -36(%rdi) 410 | notq -4(%rdi) 411 | notq 36(%rdi) 412 | notq 60(%rdi) 413 | 414 | leaq 280(%rsp),%r11 415 | 416 | movq -48(%r11),%r15 417 | movq -40(%r11),%r14 418 | movq -32(%r11),%r13 419 | movq -24(%r11),%r12 420 | movq -16(%r11),%rbp 421 | movq -8(%r11),%rbx 422 | leaq (%r11),%rsp 423 | .LSEH_epilogue_SHA3_absorb: 424 | mov 8(%r11),%rdi 425 | mov 16(%r11),%rsi 426 | 427 | .byte 0xf3,0xc3 428 | 429 | .LSEH_end_SHA3_absorb: 430 | .globl SHA3_squeeze 431 | .def SHA3_squeeze; .scl 2; .type 32; .endef 432 | .p2align 5 433 | SHA3_squeeze: 434 | .byte 0xf3,0x0f,0x1e,0xfa 435 | movq %rdi,8(%rsp) 436 | movq %rsi,16(%rsp) 437 | movq %rsp,%r11 438 | .LSEH_begin_SHA3_squeeze: 439 | 440 | 441 | movq %rcx,%rdi 442 | movq %rdx,%rsi 443 | movq %r8,%rdx 444 | movq %r9,%rcx 445 | pushq %r12 446 | 447 | pushq %r13 448 | 449 | pushq %r14 450 | 451 | subq $32,%rsp 452 | 453 | .LSEH_body_SHA3_squeeze: 454 | 455 | 456 | shrq $3,%rcx 457 | movq %rdi,%r8 458 | movq %rsi,%r12 459 | movq %rdx,%r13 460 | movq %rcx,%r14 461 | jmp .Loop_squeeze 462 | 463 | .p2align 5 464 | .Loop_squeeze: 465 | cmpq $8,%r13 466 | jb .Ltail_squeeze 467 | 468 | movq (%r8),%rax 469 | leaq 8(%r8),%r8 470 | movq %rax,(%r12) 471 | leaq 8(%r12),%r12 472 | subq $8,%r13 473 | jz .Ldone_squeeze 474 | 475 | subq $1,%rcx 476 | jnz .Loop_squeeze 477 | 478 | movq %rdi,%rcx 479 | call KeccakF1600 480 | movq %rdi,%r8 481 | movq %r14,%rcx 482 | jmp .Loop_squeeze 483 | 484 | .Ltail_squeeze: 485 | movq %r8,%rsi 486 | movq %r12,%rdi 487 | movq %r13,%rcx 488 | .byte 0xf3,0xa4 489 | 490 | .Ldone_squeeze: 491 | movq 32(%rsp),%r14 492 | movq 40(%rsp),%r13 493 | movq 48(%rsp),%r12 494 | addq $56,%rsp 495 | 496 | .LSEH_epilogue_SHA3_squeeze: 497 | mov 8(%rsp),%rdi 498 | mov 16(%rsp),%rsi 499 | 500 | .byte 0xf3,0xc3 501 | 502 | .LSEH_end_SHA3_squeeze: 503 | .p2align 8 504 | .quad 0,0,0,0,0,0,0,0 505 | 506 | iotas: 507 | .quad 0x0000000000000001 508 | .quad 0x0000000000008082 509 | .quad 0x800000000000808a 510 | .quad 0x8000000080008000 511 | .quad 0x000000000000808b 512 | .quad 0x0000000080000001 513 | .quad 0x8000000080008081 514 | .quad 0x8000000000008009 515 | .quad 0x000000000000008a 516 | .quad 0x0000000000000088 517 | .quad 0x0000000080008009 518 | .quad 0x000000008000000a 519 | .quad 0x000000008000808b 520 | .quad 0x800000000000008b 521 | .quad 0x8000000000008089 522 | .quad 0x8000000000008003 523 | .quad 0x8000000000008002 524 | .quad 0x8000000000000080 525 | .quad 0x000000000000800a 526 | .quad 0x800000008000000a 527 | .quad 0x8000000080008081 528 | .quad 0x8000000000008080 529 | .quad 0x0000000080000001 530 | .quad 0x8000000080008008 531 | 532 | .byte 75,101,99,99,97,107,45,49,54,48,48,32,97,98,115,111,114,98,32,97,110,100,32,115,113,117,101,101,122,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 533 | .section .pdata 534 | .p2align 2 535 | .rva .LSEH_begin_KeccakF1600 536 | .rva .LSEH_body_KeccakF1600 537 | .rva .LSEH_info_KeccakF1600_prologue 538 | 539 | .rva .LSEH_body_KeccakF1600 540 | .rva .LSEH_epilogue_KeccakF1600 541 | .rva .LSEH_info_KeccakF1600_body 542 | 543 | .rva .LSEH_epilogue_KeccakF1600 544 | .rva .LSEH_end_KeccakF1600 545 | .rva .LSEH_info_KeccakF1600_epilogue 546 | 547 | .rva .LSEH_begin_SHA3_absorb 548 | .rva .LSEH_body_SHA3_absorb 549 | .rva .LSEH_info_SHA3_absorb_prologue 550 | 551 | .rva .LSEH_body_SHA3_absorb 552 | .rva .LSEH_epilogue_SHA3_absorb 553 | .rva .LSEH_info_SHA3_absorb_body 554 | 555 | .rva .LSEH_epilogue_SHA3_absorb 556 | .rva .LSEH_end_SHA3_absorb 557 | .rva .LSEH_info_SHA3_absorb_epilogue 558 | 559 | .rva .LSEH_begin_SHA3_squeeze 560 | .rva .LSEH_body_SHA3_squeeze 561 | .rva .LSEH_info_SHA3_squeeze_prologue 562 | 563 | .rva .LSEH_body_SHA3_squeeze 564 | .rva .LSEH_epilogue_SHA3_squeeze 565 | .rva .LSEH_info_SHA3_squeeze_body 566 | 567 | .rva .LSEH_epilogue_SHA3_squeeze 568 | .rva .LSEH_end_SHA3_squeeze 569 | .rva .LSEH_info_SHA3_squeeze_epilogue 570 | 571 | .section .xdata 572 | .p2align 3 573 | .LSEH_info_KeccakF1600_prologue: 574 | .byte 1,0,5,0x0b 575 | .byte 0,0x74,1,0 576 | .byte 0,0x64,2,0 577 | .byte 0,0xb3 578 | .byte 0,0 579 | .long 0,0 580 | .LSEH_info_KeccakF1600_body: 581 | .byte 1,0,18,0 582 | .byte 0x00,0xf4,0x19,0x00 583 | .byte 0x00,0xe4,0x1a,0x00 584 | .byte 0x00,0xd4,0x1b,0x00 585 | .byte 0x00,0xc4,0x1c,0x00 586 | .byte 0x00,0x54,0x1d,0x00 587 | .byte 0x00,0x34,0x1e,0x00 588 | .byte 0x00,0x74,0x20,0x00 589 | .byte 0x00,0x64,0x21,0x00 590 | .byte 0x00,0x01,0x1f,0x00 591 | .byte 0x00,0x00,0x00,0x00 592 | .byte 0x00,0x00,0x00,0x00 593 | .LSEH_info_KeccakF1600_epilogue: 594 | .byte 1,0,5,11 595 | .byte 0x00,0x74,0x01,0x00 596 | .byte 0x00,0x64,0x02,0x00 597 | .byte 0x00,0xb3 598 | .byte 0x00,0x00,0x00,0x00,0x00,0x00 599 | .byte 0x00,0x00,0x00,0x00 600 | 601 | .LSEH_info_SHA3_absorb_prologue: 602 | .byte 1,0,5,0x0b 603 | .byte 0,0x74,1,0 604 | .byte 0,0x64,2,0 605 | .byte 0,0xb3 606 | .byte 0,0 607 | .long 0,0 608 | .LSEH_info_SHA3_absorb_body: 609 | .byte 1,0,18,0 610 | .byte 0x00,0xf4,0x1d,0x00 611 | .byte 0x00,0xe4,0x1e,0x00 612 | .byte 0x00,0xd4,0x1f,0x00 613 | .byte 0x00,0xc4,0x20,0x00 614 | .byte 0x00,0x54,0x21,0x00 615 | .byte 0x00,0x34,0x22,0x00 616 | .byte 0x00,0x74,0x24,0x00 617 | .byte 0x00,0x64,0x25,0x00 618 | .byte 0x00,0x01,0x23,0x00 619 | .byte 0x00,0x00,0x00,0x00 620 | .byte 0x00,0x00,0x00,0x00 621 | .LSEH_info_SHA3_absorb_epilogue: 622 | .byte 1,0,5,11 623 | .byte 0x00,0x74,0x01,0x00 624 | .byte 0x00,0x64,0x02,0x00 625 | .byte 0x00,0xb3 626 | .byte 0x00,0x00,0x00,0x00,0x00,0x00 627 | .byte 0x00,0x00,0x00,0x00 628 | 629 | .LSEH_info_SHA3_squeeze_prologue: 630 | .byte 1,0,5,0x0b 631 | .byte 0,0x74,1,0 632 | .byte 0,0x64,2,0 633 | .byte 0,0xb3 634 | .byte 0,0 635 | .long 0,0 636 | .LSEH_info_SHA3_squeeze_body: 637 | .byte 1,0,11,0 638 | .byte 0x00,0xe4,0x04,0x00 639 | .byte 0x00,0xd4,0x05,0x00 640 | .byte 0x00,0xc4,0x06,0x00 641 | .byte 0x00,0x74,0x08,0x00 642 | .byte 0x00,0x64,0x09,0x00 643 | .byte 0x00,0x62 644 | .byte 0x00,0x00,0x00,0x00,0x00,0x00 645 | .LSEH_info_SHA3_squeeze_epilogue: 646 | .byte 1,0,4,0 647 | .byte 0x00,0x74,0x01,0x00 648 | .byte 0x00,0x64,0x02,0x00 649 | .byte 0x00,0x00,0x00,0x00 650 | 651 | -------------------------------------------------------------------------------- /src/asm/keccakf1600_x86-64-msvc.asm: -------------------------------------------------------------------------------- 1 | OPTION DOTNAME 2 | .text$ SEGMENT ALIGN(256) 'CODE' 3 | 4 | 5 | ALIGN 32 6 | __KeccakF1600 PROC PRIVATE 7 | DB 243,15,30,250 8 | 9 | mov rax,QWORD PTR[60+rdi] 10 | mov rbx,QWORD PTR[68+rdi] 11 | mov rcx,QWORD PTR[76+rdi] 12 | mov rdx,QWORD PTR[84+rdi] 13 | mov rbp,QWORD PTR[92+rdi] 14 | jmp $L$oop 15 | 16 | ALIGN 32 17 | $L$oop:: 18 | mov r8,QWORD PTR[((-100))+rdi] 19 | mov r9,QWORD PTR[((-52))+rdi] 20 | mov r10,QWORD PTR[((-4))+rdi] 21 | mov r11,QWORD PTR[44+rdi] 22 | 23 | xor rcx,QWORD PTR[((-84))+rdi] 24 | xor rdx,QWORD PTR[((-76))+rdi] 25 | xor rax,r8 26 | xor rbx,QWORD PTR[((-92))+rdi] 27 | xor rcx,QWORD PTR[((-44))+rdi] 28 | xor rax,QWORD PTR[((-60))+rdi] 29 | mov r12,rbp 30 | xor rbp,QWORD PTR[((-68))+rdi] 31 | 32 | xor rcx,r10 33 | xor rax,QWORD PTR[((-20))+rdi] 34 | xor rdx,QWORD PTR[((-36))+rdi] 35 | xor rbx,r9 36 | xor rbp,QWORD PTR[((-28))+rdi] 37 | 38 | xor rcx,QWORD PTR[36+rdi] 39 | xor rax,QWORD PTR[20+rdi] 40 | xor rdx,QWORD PTR[4+rdi] 41 | xor rbx,QWORD PTR[((-12))+rdi] 42 | xor rbp,QWORD PTR[12+rdi] 43 | 44 | mov r13,rcx 45 | rol rcx,1 46 | xor rcx,rax 47 | xor rdx,r11 48 | 49 | rol rax,1 50 | xor rax,rdx 51 | xor rbx,QWORD PTR[28+rdi] 52 | 53 | rol rdx,1 54 | xor rdx,rbx 55 | xor rbp,QWORD PTR[52+rdi] 56 | 57 | rol rbx,1 58 | xor rbx,rbp 59 | 60 | rol rbp,1 61 | xor rbp,r13 62 | xor r9,rcx 63 | xor r10,rdx 64 | rol r9,44 65 | xor r11,rbp 66 | xor r12,rax 67 | rol r10,43 68 | xor r8,rbx 69 | mov r13,r9 70 | rol r11,21 71 | or r9,r10 72 | xor r9,r8 73 | rol r12,14 74 | 75 | xor r9,QWORD PTR[r15] 76 | lea r15,QWORD PTR[8+r15] 77 | 78 | mov r14,r12 79 | and r12,r11 80 | mov QWORD PTR[((-100))+rsi],r9 81 | xor r12,r10 82 | not r10 83 | mov QWORD PTR[((-84))+rsi],r12 84 | 85 | or r10,r11 86 | mov r12,QWORD PTR[76+rdi] 87 | xor r10,r13 88 | mov QWORD PTR[((-92))+rsi],r10 89 | 90 | and r13,r8 91 | mov r9,QWORD PTR[((-28))+rdi] 92 | xor r13,r14 93 | mov r10,QWORD PTR[((-20))+rdi] 94 | mov QWORD PTR[((-68))+rsi],r13 95 | 96 | or r14,r8 97 | mov r8,QWORD PTR[((-76))+rdi] 98 | xor r14,r11 99 | mov r11,QWORD PTR[28+rdi] 100 | mov QWORD PTR[((-76))+rsi],r14 101 | 102 | 103 | xor r8,rbp 104 | xor r12,rdx 105 | rol r8,28 106 | xor r11,rcx 107 | xor r9,rax 108 | rol r12,61 109 | rol r11,45 110 | xor r10,rbx 111 | rol r9,20 112 | mov r13,r8 113 | or r8,r12 114 | rol r10,3 115 | 116 | xor r8,r11 117 | mov QWORD PTR[((-36))+rsi],r8 118 | 119 | mov r14,r9 120 | and r9,r13 121 | mov r8,QWORD PTR[((-92))+rdi] 122 | xor r9,r12 123 | not r12 124 | mov QWORD PTR[((-28))+rsi],r9 125 | 126 | or r12,r11 127 | mov r9,QWORD PTR[((-44))+rdi] 128 | xor r12,r10 129 | mov QWORD PTR[((-44))+rsi],r12 130 | 131 | and r11,r10 132 | mov r12,QWORD PTR[60+rdi] 133 | xor r11,r14 134 | mov QWORD PTR[((-52))+rsi],r11 135 | 136 | or r14,r10 137 | mov r10,QWORD PTR[4+rdi] 138 | xor r14,r13 139 | mov r11,QWORD PTR[52+rdi] 140 | mov QWORD PTR[((-60))+rsi],r14 141 | 142 | 143 | xor r10,rbp 144 | xor r11,rax 145 | rol r10,25 146 | xor r9,rdx 147 | rol r11,8 148 | xor r12,rbx 149 | rol r9,6 150 | xor r8,rcx 151 | rol r12,18 152 | mov r13,r10 153 | and r10,r11 154 | rol r8,1 155 | 156 | not r11 157 | xor r10,r9 158 | mov QWORD PTR[((-12))+rsi],r10 159 | 160 | mov r14,r12 161 | and r12,r11 162 | mov r10,QWORD PTR[((-12))+rdi] 163 | xor r12,r13 164 | mov QWORD PTR[((-4))+rsi],r12 165 | 166 | or r13,r9 167 | mov r12,QWORD PTR[84+rdi] 168 | xor r13,r8 169 | mov QWORD PTR[((-20))+rsi],r13 170 | 171 | and r9,r8 172 | xor r9,r14 173 | mov QWORD PTR[12+rsi],r9 174 | 175 | or r14,r8 176 | mov r9,QWORD PTR[((-60))+rdi] 177 | xor r14,r11 178 | mov r11,QWORD PTR[36+rdi] 179 | mov QWORD PTR[4+rsi],r14 180 | 181 | 182 | mov r8,QWORD PTR[((-68))+rdi] 183 | 184 | xor r10,rcx 185 | xor r11,rdx 186 | rol r10,10 187 | xor r9,rbx 188 | rol r11,15 189 | xor r12,rbp 190 | rol r9,36 191 | xor r8,rax 192 | rol r12,56 193 | mov r13,r10 194 | or r10,r11 195 | rol r8,27 196 | 197 | not r11 198 | xor r10,r9 199 | mov QWORD PTR[28+rsi],r10 200 | 201 | mov r14,r12 202 | or r12,r11 203 | xor r12,r13 204 | mov QWORD PTR[36+rsi],r12 205 | 206 | and r13,r9 207 | xor r13,r8 208 | mov QWORD PTR[20+rsi],r13 209 | 210 | or r9,r8 211 | xor r9,r14 212 | mov QWORD PTR[52+rsi],r9 213 | 214 | and r8,r14 215 | xor r8,r11 216 | mov QWORD PTR[44+rsi],r8 217 | 218 | 219 | xor rdx,QWORD PTR[((-84))+rdi] 220 | xor rbp,QWORD PTR[((-36))+rdi] 221 | rol rdx,62 222 | xor rcx,QWORD PTR[68+rdi] 223 | rol rbp,55 224 | xor rax,QWORD PTR[12+rdi] 225 | rol rcx,2 226 | xor rbx,QWORD PTR[20+rdi] 227 | xchg rdi,rsi 228 | rol rax,39 229 | rol rbx,41 230 | mov r13,rdx 231 | and rdx,rbp 232 | not rbp 233 | xor rdx,rcx 234 | mov QWORD PTR[92+rdi],rdx 235 | 236 | mov r14,rax 237 | and rax,rbp 238 | xor rax,r13 239 | mov QWORD PTR[60+rdi],rax 240 | 241 | or r13,rcx 242 | xor r13,rbx 243 | mov QWORD PTR[84+rdi],r13 244 | 245 | and rcx,rbx 246 | xor rcx,r14 247 | mov QWORD PTR[76+rdi],rcx 248 | 249 | or rbx,r14 250 | xor rbx,rbp 251 | mov QWORD PTR[68+rdi],rbx 252 | 253 | mov rbp,rdx 254 | mov rdx,r13 255 | 256 | test r15,255 257 | jnz $L$oop 258 | 259 | lea r15,QWORD PTR[((-192))+r15] 260 | DB 0F3h,0C3h ;repret 261 | __KeccakF1600 ENDP 262 | 263 | PUBLIC KeccakF1600 264 | 265 | ALIGN 32 266 | KeccakF1600 PROC PUBLIC 267 | DB 243,15,30,250 268 | mov QWORD PTR[8+rsp],rdi ;WIN64 prologue 269 | mov QWORD PTR[16+rsp],rsi 270 | mov r11,rsp 271 | $L$SEH_begin_KeccakF1600:: 272 | 273 | 274 | mov rdi,rcx 275 | push rbx 276 | 277 | push rbp 278 | 279 | push r12 280 | 281 | push r13 282 | 283 | push r14 284 | 285 | push r15 286 | 287 | 288 | lea rdi,QWORD PTR[100+rdi] 289 | sub rsp,200 290 | 291 | $L$SEH_body_KeccakF1600:: 292 | 293 | 294 | not QWORD PTR[((-92))+rdi] 295 | not QWORD PTR[((-84))+rdi] 296 | not QWORD PTR[((-36))+rdi] 297 | not QWORD PTR[((-4))+rdi] 298 | not QWORD PTR[36+rdi] 299 | not QWORD PTR[60+rdi] 300 | 301 | lea r15,QWORD PTR[iotas] 302 | lea rsi,QWORD PTR[100+rsp] 303 | 304 | call __KeccakF1600 305 | 306 | not QWORD PTR[((-92))+rdi] 307 | not QWORD PTR[((-84))+rdi] 308 | not QWORD PTR[((-36))+rdi] 309 | not QWORD PTR[((-4))+rdi] 310 | not QWORD PTR[36+rdi] 311 | not QWORD PTR[60+rdi] 312 | lea rdi,QWORD PTR[((-100))+rdi] 313 | 314 | lea r11,QWORD PTR[248+rsp] 315 | 316 | mov r15,QWORD PTR[((-48))+r11] 317 | mov r14,QWORD PTR[((-40))+r11] 318 | mov r13,QWORD PTR[((-32))+r11] 319 | mov r12,QWORD PTR[((-24))+r11] 320 | mov rbp,QWORD PTR[((-16))+r11] 321 | mov rbx,QWORD PTR[((-8))+r11] 322 | lea rsp,QWORD PTR[r11] 323 | $L$SEH_epilogue_KeccakF1600:: 324 | mov rdi,QWORD PTR[8+r11] ;WIN64 epilogue 325 | mov rsi,QWORD PTR[16+r11] 326 | 327 | DB 0F3h,0C3h ;repret 328 | 329 | $L$SEH_end_KeccakF1600:: 330 | KeccakF1600 ENDP 331 | PUBLIC SHA3_absorb 332 | 333 | ALIGN 32 334 | SHA3_absorb PROC PUBLIC 335 | DB 243,15,30,250 336 | mov QWORD PTR[8+rsp],rdi ;WIN64 prologue 337 | mov QWORD PTR[16+rsp],rsi 338 | mov r11,rsp 339 | $L$SEH_begin_SHA3_absorb:: 340 | 341 | 342 | mov rdi,rcx 343 | mov rsi,rdx 344 | mov rdx,r8 345 | mov rcx,r9 346 | push rbx 347 | 348 | push rbp 349 | 350 | push r12 351 | 352 | push r13 353 | 354 | push r14 355 | 356 | push r15 357 | 358 | 359 | lea rdi,QWORD PTR[100+rdi] 360 | sub rsp,232 361 | 362 | $L$SEH_body_SHA3_absorb:: 363 | 364 | 365 | mov r9,rsi 366 | lea rsi,QWORD PTR[100+rsp] 367 | 368 | not QWORD PTR[((-92))+rdi] 369 | not QWORD PTR[((-84))+rdi] 370 | not QWORD PTR[((-36))+rdi] 371 | not QWORD PTR[((-4))+rdi] 372 | not QWORD PTR[36+rdi] 373 | not QWORD PTR[60+rdi] 374 | lea r15,QWORD PTR[iotas] 375 | 376 | mov QWORD PTR[((216-100))+rsi],rcx 377 | 378 | $L$oop_absorb:: 379 | cmp rdx,rcx 380 | jc $L$done_absorb 381 | 382 | shr rcx,3 383 | lea r8,QWORD PTR[((-100))+rdi] 384 | 385 | $L$block_absorb:: 386 | mov rax,QWORD PTR[r9] 387 | lea r9,QWORD PTR[8+r9] 388 | xor rax,QWORD PTR[r8] 389 | lea r8,QWORD PTR[8+r8] 390 | sub rdx,8 391 | mov QWORD PTR[((-8))+r8],rax 392 | sub rcx,1 393 | jnz $L$block_absorb 394 | 395 | mov QWORD PTR[((200-100))+rsi],r9 396 | mov QWORD PTR[((208-100))+rsi],rdx 397 | call __KeccakF1600 398 | mov r9,QWORD PTR[((200-100))+rsi] 399 | mov rdx,QWORD PTR[((208-100))+rsi] 400 | mov rcx,QWORD PTR[((216-100))+rsi] 401 | jmp $L$oop_absorb 402 | 403 | ALIGN 32 404 | $L$done_absorb:: 405 | mov rax,rdx 406 | 407 | not QWORD PTR[((-92))+rdi] 408 | not QWORD PTR[((-84))+rdi] 409 | not QWORD PTR[((-36))+rdi] 410 | not QWORD PTR[((-4))+rdi] 411 | not QWORD PTR[36+rdi] 412 | not QWORD PTR[60+rdi] 413 | 414 | lea r11,QWORD PTR[280+rsp] 415 | 416 | mov r15,QWORD PTR[((-48))+r11] 417 | mov r14,QWORD PTR[((-40))+r11] 418 | mov r13,QWORD PTR[((-32))+r11] 419 | mov r12,QWORD PTR[((-24))+r11] 420 | mov rbp,QWORD PTR[((-16))+r11] 421 | mov rbx,QWORD PTR[((-8))+r11] 422 | lea rsp,QWORD PTR[r11] 423 | $L$SEH_epilogue_SHA3_absorb:: 424 | mov rdi,QWORD PTR[8+r11] ;WIN64 epilogue 425 | mov rsi,QWORD PTR[16+r11] 426 | 427 | DB 0F3h,0C3h ;repret 428 | 429 | $L$SEH_end_SHA3_absorb:: 430 | SHA3_absorb ENDP 431 | PUBLIC SHA3_squeeze 432 | 433 | ALIGN 32 434 | SHA3_squeeze PROC PUBLIC 435 | DB 243,15,30,250 436 | mov QWORD PTR[8+rsp],rdi ;WIN64 prologue 437 | mov QWORD PTR[16+rsp],rsi 438 | mov r11,rsp 439 | $L$SEH_begin_SHA3_squeeze:: 440 | 441 | 442 | mov rdi,rcx 443 | mov rsi,rdx 444 | mov rdx,r8 445 | mov rcx,r9 446 | push r12 447 | 448 | push r13 449 | 450 | push r14 451 | 452 | sub rsp,32 453 | 454 | $L$SEH_body_SHA3_squeeze:: 455 | 456 | 457 | shr rcx,3 458 | mov r8,rdi 459 | mov r12,rsi 460 | mov r13,rdx 461 | mov r14,rcx 462 | jmp $L$oop_squeeze 463 | 464 | ALIGN 32 465 | $L$oop_squeeze:: 466 | cmp r13,8 467 | jb $L$tail_squeeze 468 | 469 | mov rax,QWORD PTR[r8] 470 | lea r8,QWORD PTR[8+r8] 471 | mov QWORD PTR[r12],rax 472 | lea r12,QWORD PTR[8+r12] 473 | sub r13,8 474 | jz $L$done_squeeze 475 | 476 | sub rcx,1 477 | jnz $L$oop_squeeze 478 | 479 | mov rcx,rdi 480 | call KeccakF1600 481 | mov r8,rdi 482 | mov rcx,r14 483 | jmp $L$oop_squeeze 484 | 485 | $L$tail_squeeze:: 486 | mov rsi,r8 487 | mov rdi,r12 488 | mov rcx,r13 489 | DB 0f3h,0a4h 490 | 491 | $L$done_squeeze:: 492 | mov r14,QWORD PTR[32+rsp] 493 | mov r13,QWORD PTR[40+rsp] 494 | mov r12,QWORD PTR[48+rsp] 495 | add rsp,56 496 | 497 | $L$SEH_epilogue_SHA3_squeeze:: 498 | mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue 499 | mov rsi,QWORD PTR[16+rsp] 500 | 501 | DB 0F3h,0C3h ;repret 502 | 503 | $L$SEH_end_SHA3_squeeze:: 504 | SHA3_squeeze ENDP 505 | ALIGN 256 506 | DQ 0,0,0,0,0,0,0,0 507 | 508 | iotas:: 509 | DQ 00000000000000001h 510 | DQ 00000000000008082h 511 | DQ 0800000000000808ah 512 | DQ 08000000080008000h 513 | DQ 0000000000000808bh 514 | DQ 00000000080000001h 515 | DQ 08000000080008081h 516 | DQ 08000000000008009h 517 | DQ 0000000000000008ah 518 | DQ 00000000000000088h 519 | DQ 00000000080008009h 520 | DQ 0000000008000000ah 521 | DQ 0000000008000808bh 522 | DQ 0800000000000008bh 523 | DQ 08000000000008089h 524 | DQ 08000000000008003h 525 | DQ 08000000000008002h 526 | DQ 08000000000000080h 527 | DQ 0000000000000800ah 528 | DQ 0800000008000000ah 529 | DQ 08000000080008081h 530 | DQ 08000000000008080h 531 | DQ 00000000080000001h 532 | DQ 08000000080008008h 533 | 534 | DB 75,101,99,99,97,107,45,49,54,48,48,32,97,98,115,111 535 | DB 114,98,32,97,110,100,32,115,113,117,101,101,122,101,32,102 536 | DB 111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84 537 | DB 79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64 538 | DB 111,112,101,110,115,115,108,46,111,114,103,62,0 539 | .text$ ENDS 540 | .pdata SEGMENT READONLY ALIGN(4) 541 | ALIGN 4 542 | DD imagerel $L$SEH_begin_KeccakF1600 543 | DD imagerel $L$SEH_body_KeccakF1600 544 | DD imagerel $L$SEH_info_KeccakF1600_prologue 545 | 546 | DD imagerel $L$SEH_body_KeccakF1600 547 | DD imagerel $L$SEH_epilogue_KeccakF1600 548 | DD imagerel $L$SEH_info_KeccakF1600_body 549 | 550 | DD imagerel $L$SEH_epilogue_KeccakF1600 551 | DD imagerel $L$SEH_end_KeccakF1600 552 | DD imagerel $L$SEH_info_KeccakF1600_epilogue 553 | 554 | DD imagerel $L$SEH_begin_SHA3_absorb 555 | DD imagerel $L$SEH_body_SHA3_absorb 556 | DD imagerel $L$SEH_info_SHA3_absorb_prologue 557 | 558 | DD imagerel $L$SEH_body_SHA3_absorb 559 | DD imagerel $L$SEH_epilogue_SHA3_absorb 560 | DD imagerel $L$SEH_info_SHA3_absorb_body 561 | 562 | DD imagerel $L$SEH_epilogue_SHA3_absorb 563 | DD imagerel $L$SEH_end_SHA3_absorb 564 | DD imagerel $L$SEH_info_SHA3_absorb_epilogue 565 | 566 | DD imagerel $L$SEH_begin_SHA3_squeeze 567 | DD imagerel $L$SEH_body_SHA3_squeeze 568 | DD imagerel $L$SEH_info_SHA3_squeeze_prologue 569 | 570 | DD imagerel $L$SEH_body_SHA3_squeeze 571 | DD imagerel $L$SEH_epilogue_SHA3_squeeze 572 | DD imagerel $L$SEH_info_SHA3_squeeze_body 573 | 574 | DD imagerel $L$SEH_epilogue_SHA3_squeeze 575 | DD imagerel $L$SEH_end_SHA3_squeeze 576 | DD imagerel $L$SEH_info_SHA3_squeeze_epilogue 577 | 578 | .pdata ENDS 579 | .xdata SEGMENT READONLY ALIGN(8) 580 | ALIGN 8 581 | $L$SEH_info_KeccakF1600_prologue:: 582 | DB 1,0,5,00bh 583 | DB 0,074h,1,0 584 | DB 0,064h,2,0 585 | DB 0,0b3h 586 | DB 0,0 587 | DD 0,0 588 | $L$SEH_info_KeccakF1600_body:: 589 | DB 1,0,18,0 590 | DB 000h,0f4h,019h,000h 591 | DB 000h,0e4h,01ah,000h 592 | DB 000h,0d4h,01bh,000h 593 | DB 000h,0c4h,01ch,000h 594 | DB 000h,054h,01dh,000h 595 | DB 000h,034h,01eh,000h 596 | DB 000h,074h,020h,000h 597 | DB 000h,064h,021h,000h 598 | DB 000h,001h,01fh,000h 599 | DB 000h,000h,000h,000h 600 | DB 000h,000h,000h,000h 601 | $L$SEH_info_KeccakF1600_epilogue:: 602 | DB 1,0,5,11 603 | DB 000h,074h,001h,000h 604 | DB 000h,064h,002h,000h 605 | DB 000h,0b3h 606 | DB 000h,000h,000h,000h,000h,000h 607 | DB 000h,000h,000h,000h 608 | 609 | $L$SEH_info_SHA3_absorb_prologue:: 610 | DB 1,0,5,00bh 611 | DB 0,074h,1,0 612 | DB 0,064h,2,0 613 | DB 0,0b3h 614 | DB 0,0 615 | DD 0,0 616 | $L$SEH_info_SHA3_absorb_body:: 617 | DB 1,0,18,0 618 | DB 000h,0f4h,01dh,000h 619 | DB 000h,0e4h,01eh,000h 620 | DB 000h,0d4h,01fh,000h 621 | DB 000h,0c4h,020h,000h 622 | DB 000h,054h,021h,000h 623 | DB 000h,034h,022h,000h 624 | DB 000h,074h,024h,000h 625 | DB 000h,064h,025h,000h 626 | DB 000h,001h,023h,000h 627 | DB 000h,000h,000h,000h 628 | DB 000h,000h,000h,000h 629 | $L$SEH_info_SHA3_absorb_epilogue:: 630 | DB 1,0,5,11 631 | DB 000h,074h,001h,000h 632 | DB 000h,064h,002h,000h 633 | DB 000h,0b3h 634 | DB 000h,000h,000h,000h,000h,000h 635 | DB 000h,000h,000h,000h 636 | 637 | $L$SEH_info_SHA3_squeeze_prologue:: 638 | DB 1,0,5,00bh 639 | DB 0,074h,1,0 640 | DB 0,064h,2,0 641 | DB 0,0b3h 642 | DB 0,0 643 | DD 0,0 644 | $L$SEH_info_SHA3_squeeze_body:: 645 | DB 1,0,11,0 646 | DB 000h,0e4h,004h,000h 647 | DB 000h,0d4h,005h,000h 648 | DB 000h,0c4h,006h,000h 649 | DB 000h,074h,008h,000h 650 | DB 000h,064h,009h,000h 651 | DB 000h,062h 652 | DB 000h,000h,000h,000h,000h,000h 653 | $L$SEH_info_SHA3_squeeze_epilogue:: 654 | DB 1,0,4,0 655 | DB 000h,074h,001h,000h 656 | DB 000h,064h,002h,000h 657 | DB 000h,000h,000h,000h 658 | 659 | 660 | .xdata ENDS 661 | END 662 | -------------------------------------------------------------------------------- /src/asm/keccakf1600_x86-64-osx.s: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/dot-asm/cryptogams/blob/master/x86_64/keccak1600-x86_64.pl 2 | 3 | .text 4 | 5 | 6 | .p2align 5 7 | __KeccakF1600: 8 | .cfi_startproc 9 | .byte 0xf3,0x0f,0x1e,0xfa 10 | 11 | movq 60(%rdi),%rax 12 | movq 68(%rdi),%rbx 13 | movq 76(%rdi),%rcx 14 | movq 84(%rdi),%rdx 15 | movq 92(%rdi),%rbp 16 | jmp L$oop 17 | 18 | .p2align 5 19 | L$oop: 20 | movq -100(%rdi),%r8 21 | movq -52(%rdi),%r9 22 | movq -4(%rdi),%r10 23 | movq 44(%rdi),%r11 24 | 25 | xorq -84(%rdi),%rcx 26 | xorq -76(%rdi),%rdx 27 | xorq %r8,%rax 28 | xorq -92(%rdi),%rbx 29 | xorq -44(%rdi),%rcx 30 | xorq -60(%rdi),%rax 31 | movq %rbp,%r12 32 | xorq -68(%rdi),%rbp 33 | 34 | xorq %r10,%rcx 35 | xorq -20(%rdi),%rax 36 | xorq -36(%rdi),%rdx 37 | xorq %r9,%rbx 38 | xorq -28(%rdi),%rbp 39 | 40 | xorq 36(%rdi),%rcx 41 | xorq 20(%rdi),%rax 42 | xorq 4(%rdi),%rdx 43 | xorq -12(%rdi),%rbx 44 | xorq 12(%rdi),%rbp 45 | 46 | movq %rcx,%r13 47 | rolq $1,%rcx 48 | xorq %rax,%rcx 49 | xorq %r11,%rdx 50 | 51 | rolq $1,%rax 52 | xorq %rdx,%rax 53 | xorq 28(%rdi),%rbx 54 | 55 | rolq $1,%rdx 56 | xorq %rbx,%rdx 57 | xorq 52(%rdi),%rbp 58 | 59 | rolq $1,%rbx 60 | xorq %rbp,%rbx 61 | 62 | rolq $1,%rbp 63 | xorq %r13,%rbp 64 | xorq %rcx,%r9 65 | xorq %rdx,%r10 66 | rolq $44,%r9 67 | xorq %rbp,%r11 68 | xorq %rax,%r12 69 | rolq $43,%r10 70 | xorq %rbx,%r8 71 | movq %r9,%r13 72 | rolq $21,%r11 73 | orq %r10,%r9 74 | xorq %r8,%r9 75 | rolq $14,%r12 76 | 77 | xorq (%r15),%r9 78 | leaq 8(%r15),%r15 79 | 80 | movq %r12,%r14 81 | andq %r11,%r12 82 | movq %r9,-100(%rsi) 83 | xorq %r10,%r12 84 | notq %r10 85 | movq %r12,-84(%rsi) 86 | 87 | orq %r11,%r10 88 | movq 76(%rdi),%r12 89 | xorq %r13,%r10 90 | movq %r10,-92(%rsi) 91 | 92 | andq %r8,%r13 93 | movq -28(%rdi),%r9 94 | xorq %r14,%r13 95 | movq -20(%rdi),%r10 96 | movq %r13,-68(%rsi) 97 | 98 | orq %r8,%r14 99 | movq -76(%rdi),%r8 100 | xorq %r11,%r14 101 | movq 28(%rdi),%r11 102 | movq %r14,-76(%rsi) 103 | 104 | 105 | xorq %rbp,%r8 106 | xorq %rdx,%r12 107 | rolq $28,%r8 108 | xorq %rcx,%r11 109 | xorq %rax,%r9 110 | rolq $61,%r12 111 | rolq $45,%r11 112 | xorq %rbx,%r10 113 | rolq $20,%r9 114 | movq %r8,%r13 115 | orq %r12,%r8 116 | rolq $3,%r10 117 | 118 | xorq %r11,%r8 119 | movq %r8,-36(%rsi) 120 | 121 | movq %r9,%r14 122 | andq %r13,%r9 123 | movq -92(%rdi),%r8 124 | xorq %r12,%r9 125 | notq %r12 126 | movq %r9,-28(%rsi) 127 | 128 | orq %r11,%r12 129 | movq -44(%rdi),%r9 130 | xorq %r10,%r12 131 | movq %r12,-44(%rsi) 132 | 133 | andq %r10,%r11 134 | movq 60(%rdi),%r12 135 | xorq %r14,%r11 136 | movq %r11,-52(%rsi) 137 | 138 | orq %r10,%r14 139 | movq 4(%rdi),%r10 140 | xorq %r13,%r14 141 | movq 52(%rdi),%r11 142 | movq %r14,-60(%rsi) 143 | 144 | 145 | xorq %rbp,%r10 146 | xorq %rax,%r11 147 | rolq $25,%r10 148 | xorq %rdx,%r9 149 | rolq $8,%r11 150 | xorq %rbx,%r12 151 | rolq $6,%r9 152 | xorq %rcx,%r8 153 | rolq $18,%r12 154 | movq %r10,%r13 155 | andq %r11,%r10 156 | rolq $1,%r8 157 | 158 | notq %r11 159 | xorq %r9,%r10 160 | movq %r10,-12(%rsi) 161 | 162 | movq %r12,%r14 163 | andq %r11,%r12 164 | movq -12(%rdi),%r10 165 | xorq %r13,%r12 166 | movq %r12,-4(%rsi) 167 | 168 | orq %r9,%r13 169 | movq 84(%rdi),%r12 170 | xorq %r8,%r13 171 | movq %r13,-20(%rsi) 172 | 173 | andq %r8,%r9 174 | xorq %r14,%r9 175 | movq %r9,12(%rsi) 176 | 177 | orq %r8,%r14 178 | movq -60(%rdi),%r9 179 | xorq %r11,%r14 180 | movq 36(%rdi),%r11 181 | movq %r14,4(%rsi) 182 | 183 | 184 | movq -68(%rdi),%r8 185 | 186 | xorq %rcx,%r10 187 | xorq %rdx,%r11 188 | rolq $10,%r10 189 | xorq %rbx,%r9 190 | rolq $15,%r11 191 | xorq %rbp,%r12 192 | rolq $36,%r9 193 | xorq %rax,%r8 194 | rolq $56,%r12 195 | movq %r10,%r13 196 | orq %r11,%r10 197 | rolq $27,%r8 198 | 199 | notq %r11 200 | xorq %r9,%r10 201 | movq %r10,28(%rsi) 202 | 203 | movq %r12,%r14 204 | orq %r11,%r12 205 | xorq %r13,%r12 206 | movq %r12,36(%rsi) 207 | 208 | andq %r9,%r13 209 | xorq %r8,%r13 210 | movq %r13,20(%rsi) 211 | 212 | orq %r8,%r9 213 | xorq %r14,%r9 214 | movq %r9,52(%rsi) 215 | 216 | andq %r14,%r8 217 | xorq %r11,%r8 218 | movq %r8,44(%rsi) 219 | 220 | 221 | xorq -84(%rdi),%rdx 222 | xorq -36(%rdi),%rbp 223 | rolq $62,%rdx 224 | xorq 68(%rdi),%rcx 225 | rolq $55,%rbp 226 | xorq 12(%rdi),%rax 227 | rolq $2,%rcx 228 | xorq 20(%rdi),%rbx 229 | xchgq %rsi,%rdi 230 | rolq $39,%rax 231 | rolq $41,%rbx 232 | movq %rdx,%r13 233 | andq %rbp,%rdx 234 | notq %rbp 235 | xorq %rcx,%rdx 236 | movq %rdx,92(%rdi) 237 | 238 | movq %rax,%r14 239 | andq %rbp,%rax 240 | xorq %r13,%rax 241 | movq %rax,60(%rdi) 242 | 243 | orq %rcx,%r13 244 | xorq %rbx,%r13 245 | movq %r13,84(%rdi) 246 | 247 | andq %rbx,%rcx 248 | xorq %r14,%rcx 249 | movq %rcx,76(%rdi) 250 | 251 | orq %r14,%rbx 252 | xorq %rbp,%rbx 253 | movq %rbx,68(%rdi) 254 | 255 | movq %rdx,%rbp 256 | movq %r13,%rdx 257 | 258 | testq $255,%r15 259 | jnz L$oop 260 | 261 | leaq -192(%r15),%r15 262 | .byte 0xf3,0xc3 263 | .cfi_endproc 264 | 265 | 266 | .globl _KeccakF1600 267 | 268 | .p2align 5 269 | _KeccakF1600: 270 | .cfi_startproc 271 | .byte 0xf3,0x0f,0x1e,0xfa 272 | 273 | 274 | pushq %rbx 275 | .cfi_adjust_cfa_offset 8 276 | .cfi_offset %rbx,-16 277 | pushq %rbp 278 | .cfi_adjust_cfa_offset 8 279 | .cfi_offset %rbp,-24 280 | pushq %r12 281 | .cfi_adjust_cfa_offset 8 282 | .cfi_offset %r12,-32 283 | pushq %r13 284 | .cfi_adjust_cfa_offset 8 285 | .cfi_offset %r13,-40 286 | pushq %r14 287 | .cfi_adjust_cfa_offset 8 288 | .cfi_offset %r14,-48 289 | pushq %r15 290 | .cfi_adjust_cfa_offset 8 291 | .cfi_offset %r15,-56 292 | 293 | leaq 100(%rdi),%rdi 294 | subq $200,%rsp 295 | .cfi_adjust_cfa_offset 200 296 | 297 | 298 | notq -92(%rdi) 299 | notq -84(%rdi) 300 | notq -36(%rdi) 301 | notq -4(%rdi) 302 | notq 36(%rdi) 303 | notq 60(%rdi) 304 | 305 | leaq iotas(%rip),%r15 306 | leaq 100(%rsp),%rsi 307 | 308 | call __KeccakF1600 309 | 310 | notq -92(%rdi) 311 | notq -84(%rdi) 312 | notq -36(%rdi) 313 | notq -4(%rdi) 314 | notq 36(%rdi) 315 | notq 60(%rdi) 316 | leaq -100(%rdi),%rdi 317 | 318 | leaq 248(%rsp),%r11 319 | .cfi_def_cfa %r11,8 320 | movq -48(%r11),%r15 321 | movq -40(%r11),%r14 322 | movq -32(%r11),%r13 323 | movq -24(%r11),%r12 324 | movq -16(%r11),%rbp 325 | movq -8(%r11),%rbx 326 | leaq (%r11),%rsp 327 | .cfi_restore %r12 328 | .cfi_restore %r13 329 | .cfi_restore %r14 330 | .cfi_restore %r15 331 | .cfi_restore %rbp 332 | .cfi_restore %rbx 333 | .byte 0xf3,0xc3 334 | .cfi_endproc 335 | 336 | .globl _SHA3_absorb 337 | 338 | .p2align 5 339 | _SHA3_absorb: 340 | .cfi_startproc 341 | .byte 0xf3,0x0f,0x1e,0xfa 342 | 343 | 344 | pushq %rbx 345 | .cfi_adjust_cfa_offset 8 346 | .cfi_offset %rbx,-16 347 | pushq %rbp 348 | .cfi_adjust_cfa_offset 8 349 | .cfi_offset %rbp,-24 350 | pushq %r12 351 | .cfi_adjust_cfa_offset 8 352 | .cfi_offset %r12,-32 353 | pushq %r13 354 | .cfi_adjust_cfa_offset 8 355 | .cfi_offset %r13,-40 356 | pushq %r14 357 | .cfi_adjust_cfa_offset 8 358 | .cfi_offset %r14,-48 359 | pushq %r15 360 | .cfi_adjust_cfa_offset 8 361 | .cfi_offset %r15,-56 362 | 363 | leaq 100(%rdi),%rdi 364 | subq $232,%rsp 365 | .cfi_adjust_cfa_offset 232 366 | 367 | 368 | movq %rsi,%r9 369 | leaq 100(%rsp),%rsi 370 | 371 | notq -92(%rdi) 372 | notq -84(%rdi) 373 | notq -36(%rdi) 374 | notq -4(%rdi) 375 | notq 36(%rdi) 376 | notq 60(%rdi) 377 | leaq iotas(%rip),%r15 378 | 379 | movq %rcx,216-100(%rsi) 380 | 381 | L$oop_absorb: 382 | cmpq %rcx,%rdx 383 | jc L$done_absorb 384 | 385 | shrq $3,%rcx 386 | leaq -100(%rdi),%r8 387 | 388 | L$block_absorb: 389 | movq (%r9),%rax 390 | leaq 8(%r9),%r9 391 | xorq (%r8),%rax 392 | leaq 8(%r8),%r8 393 | subq $8,%rdx 394 | movq %rax,-8(%r8) 395 | subq $1,%rcx 396 | jnz L$block_absorb 397 | 398 | movq %r9,200-100(%rsi) 399 | movq %rdx,208-100(%rsi) 400 | call __KeccakF1600 401 | movq 200-100(%rsi),%r9 402 | movq 208-100(%rsi),%rdx 403 | movq 216-100(%rsi),%rcx 404 | jmp L$oop_absorb 405 | 406 | .p2align 5 407 | L$done_absorb: 408 | movq %rdx,%rax 409 | 410 | notq -92(%rdi) 411 | notq -84(%rdi) 412 | notq -36(%rdi) 413 | notq -4(%rdi) 414 | notq 36(%rdi) 415 | notq 60(%rdi) 416 | 417 | leaq 280(%rsp),%r11 418 | .cfi_def_cfa %r11,8 419 | movq -48(%r11),%r15 420 | movq -40(%r11),%r14 421 | movq -32(%r11),%r13 422 | movq -24(%r11),%r12 423 | movq -16(%r11),%rbp 424 | movq -8(%r11),%rbx 425 | leaq (%r11),%rsp 426 | .cfi_restore %r12 427 | .cfi_restore %r13 428 | .cfi_restore %r14 429 | .cfi_restore %r15 430 | .cfi_restore %rbp 431 | .cfi_restore %rbx 432 | .byte 0xf3,0xc3 433 | .cfi_endproc 434 | 435 | .globl _SHA3_squeeze 436 | 437 | .p2align 5 438 | _SHA3_squeeze: 439 | .cfi_startproc 440 | .byte 0xf3,0x0f,0x1e,0xfa 441 | 442 | 443 | pushq %r12 444 | .cfi_adjust_cfa_offset 8 445 | .cfi_offset %r12,-16 446 | pushq %r13 447 | .cfi_adjust_cfa_offset 8 448 | .cfi_offset %r13,-24 449 | pushq %r14 450 | .cfi_adjust_cfa_offset 8 451 | .cfi_offset %r14,-32 452 | subq $32,%rsp 453 | .cfi_adjust_cfa_offset 32 454 | 455 | 456 | shrq $3,%rcx 457 | movq %rdi,%r8 458 | movq %rsi,%r12 459 | movq %rdx,%r13 460 | movq %rcx,%r14 461 | jmp L$oop_squeeze 462 | 463 | .p2align 5 464 | L$oop_squeeze: 465 | cmpq $8,%r13 466 | jb L$tail_squeeze 467 | 468 | movq (%r8),%rax 469 | leaq 8(%r8),%r8 470 | movq %rax,(%r12) 471 | leaq 8(%r12),%r12 472 | subq $8,%r13 473 | jz L$done_squeeze 474 | 475 | subq $1,%rcx 476 | jnz L$oop_squeeze 477 | 478 | movq %rdi,%rcx 479 | call _KeccakF1600 480 | movq %rdi,%r8 481 | movq %r14,%rcx 482 | jmp L$oop_squeeze 483 | 484 | L$tail_squeeze: 485 | movq %r8,%rsi 486 | movq %r12,%rdi 487 | movq %r13,%rcx 488 | .byte 0xf3,0xa4 489 | 490 | L$done_squeeze: 491 | movq 32(%rsp),%r14 492 | movq 40(%rsp),%r13 493 | movq 48(%rsp),%r12 494 | addq $56,%rsp 495 | .cfi_adjust_cfa_offset -56 496 | .cfi_restore %r12 497 | .cfi_restore %r13 498 | .cfi_restore %r14 499 | .byte 0xf3,0xc3 500 | .cfi_endproc 501 | 502 | .p2align 8 503 | .quad 0,0,0,0,0,0,0,0 504 | 505 | iotas: 506 | .quad 0x0000000000000001 507 | .quad 0x0000000000008082 508 | .quad 0x800000000000808a 509 | .quad 0x8000000080008000 510 | .quad 0x000000000000808b 511 | .quad 0x0000000080000001 512 | .quad 0x8000000080008081 513 | .quad 0x8000000000008009 514 | .quad 0x000000000000008a 515 | .quad 0x0000000000000088 516 | .quad 0x0000000080008009 517 | .quad 0x000000008000000a 518 | .quad 0x000000008000808b 519 | .quad 0x800000000000008b 520 | .quad 0x8000000000008089 521 | .quad 0x8000000000008003 522 | .quad 0x8000000000008002 523 | .quad 0x8000000000000080 524 | .quad 0x000000000000800a 525 | .quad 0x800000008000000a 526 | .quad 0x8000000080008081 527 | .quad 0x8000000000008080 528 | .quad 0x0000000080000001 529 | .quad 0x8000000080008008 530 | 531 | .byte 75,101,99,99,97,107,45,49,54,48,48,32,97,98,115,111,114,98,32,97,110,100,32,115,113,117,101,101,122,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 532 | -------------------------------------------------------------------------------- /src/asm/keccakf1600_x86-64-win64.s: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/dot-asm/cryptogams/blob/master/x86_64/keccak1600-x86_64.pl 2 | 3 | .text 4 | 5 | .def __KeccakF1600; .scl 3; .type 32; .endef 6 | .p2align 5 7 | __KeccakF1600: 8 | .byte 0xf3,0x0f,0x1e,0xfa 9 | 10 | movq 60(%rdi),%rax 11 | movq 68(%rdi),%rbx 12 | movq 76(%rdi),%rcx 13 | movq 84(%rdi),%rdx 14 | movq 92(%rdi),%rbp 15 | jmp .Loop 16 | 17 | .p2align 5 18 | .Loop: 19 | movq -100(%rdi),%r8 20 | movq -52(%rdi),%r9 21 | movq -4(%rdi),%r10 22 | movq 44(%rdi),%r11 23 | 24 | xorq -84(%rdi),%rcx 25 | xorq -76(%rdi),%rdx 26 | xorq %r8,%rax 27 | xorq -92(%rdi),%rbx 28 | xorq -44(%rdi),%rcx 29 | xorq -60(%rdi),%rax 30 | movq %rbp,%r12 31 | xorq -68(%rdi),%rbp 32 | 33 | xorq %r10,%rcx 34 | xorq -20(%rdi),%rax 35 | xorq -36(%rdi),%rdx 36 | xorq %r9,%rbx 37 | xorq -28(%rdi),%rbp 38 | 39 | xorq 36(%rdi),%rcx 40 | xorq 20(%rdi),%rax 41 | xorq 4(%rdi),%rdx 42 | xorq -12(%rdi),%rbx 43 | xorq 12(%rdi),%rbp 44 | 45 | movq %rcx,%r13 46 | rolq $1,%rcx 47 | xorq %rax,%rcx 48 | xorq %r11,%rdx 49 | 50 | rolq $1,%rax 51 | xorq %rdx,%rax 52 | xorq 28(%rdi),%rbx 53 | 54 | rolq $1,%rdx 55 | xorq %rbx,%rdx 56 | xorq 52(%rdi),%rbp 57 | 58 | rolq $1,%rbx 59 | xorq %rbp,%rbx 60 | 61 | rolq $1,%rbp 62 | xorq %r13,%rbp 63 | xorq %rcx,%r9 64 | xorq %rdx,%r10 65 | rolq $44,%r9 66 | xorq %rbp,%r11 67 | xorq %rax,%r12 68 | rolq $43,%r10 69 | xorq %rbx,%r8 70 | movq %r9,%r13 71 | rolq $21,%r11 72 | orq %r10,%r9 73 | xorq %r8,%r9 74 | rolq $14,%r12 75 | 76 | xorq (%r15),%r9 77 | leaq 8(%r15),%r15 78 | 79 | movq %r12,%r14 80 | andq %r11,%r12 81 | movq %r9,-100(%rsi) 82 | xorq %r10,%r12 83 | notq %r10 84 | movq %r12,-84(%rsi) 85 | 86 | orq %r11,%r10 87 | movq 76(%rdi),%r12 88 | xorq %r13,%r10 89 | movq %r10,-92(%rsi) 90 | 91 | andq %r8,%r13 92 | movq -28(%rdi),%r9 93 | xorq %r14,%r13 94 | movq -20(%rdi),%r10 95 | movq %r13,-68(%rsi) 96 | 97 | orq %r8,%r14 98 | movq -76(%rdi),%r8 99 | xorq %r11,%r14 100 | movq 28(%rdi),%r11 101 | movq %r14,-76(%rsi) 102 | 103 | 104 | xorq %rbp,%r8 105 | xorq %rdx,%r12 106 | rolq $28,%r8 107 | xorq %rcx,%r11 108 | xorq %rax,%r9 109 | rolq $61,%r12 110 | rolq $45,%r11 111 | xorq %rbx,%r10 112 | rolq $20,%r9 113 | movq %r8,%r13 114 | orq %r12,%r8 115 | rolq $3,%r10 116 | 117 | xorq %r11,%r8 118 | movq %r8,-36(%rsi) 119 | 120 | movq %r9,%r14 121 | andq %r13,%r9 122 | movq -92(%rdi),%r8 123 | xorq %r12,%r9 124 | notq %r12 125 | movq %r9,-28(%rsi) 126 | 127 | orq %r11,%r12 128 | movq -44(%rdi),%r9 129 | xorq %r10,%r12 130 | movq %r12,-44(%rsi) 131 | 132 | andq %r10,%r11 133 | movq 60(%rdi),%r12 134 | xorq %r14,%r11 135 | movq %r11,-52(%rsi) 136 | 137 | orq %r10,%r14 138 | movq 4(%rdi),%r10 139 | xorq %r13,%r14 140 | movq 52(%rdi),%r11 141 | movq %r14,-60(%rsi) 142 | 143 | 144 | xorq %rbp,%r10 145 | xorq %rax,%r11 146 | rolq $25,%r10 147 | xorq %rdx,%r9 148 | rolq $8,%r11 149 | xorq %rbx,%r12 150 | rolq $6,%r9 151 | xorq %rcx,%r8 152 | rolq $18,%r12 153 | movq %r10,%r13 154 | andq %r11,%r10 155 | rolq $1,%r8 156 | 157 | notq %r11 158 | xorq %r9,%r10 159 | movq %r10,-12(%rsi) 160 | 161 | movq %r12,%r14 162 | andq %r11,%r12 163 | movq -12(%rdi),%r10 164 | xorq %r13,%r12 165 | movq %r12,-4(%rsi) 166 | 167 | orq %r9,%r13 168 | movq 84(%rdi),%r12 169 | xorq %r8,%r13 170 | movq %r13,-20(%rsi) 171 | 172 | andq %r8,%r9 173 | xorq %r14,%r9 174 | movq %r9,12(%rsi) 175 | 176 | orq %r8,%r14 177 | movq -60(%rdi),%r9 178 | xorq %r11,%r14 179 | movq 36(%rdi),%r11 180 | movq %r14,4(%rsi) 181 | 182 | 183 | movq -68(%rdi),%r8 184 | 185 | xorq %rcx,%r10 186 | xorq %rdx,%r11 187 | rolq $10,%r10 188 | xorq %rbx,%r9 189 | rolq $15,%r11 190 | xorq %rbp,%r12 191 | rolq $36,%r9 192 | xorq %rax,%r8 193 | rolq $56,%r12 194 | movq %r10,%r13 195 | orq %r11,%r10 196 | rolq $27,%r8 197 | 198 | notq %r11 199 | xorq %r9,%r10 200 | movq %r10,28(%rsi) 201 | 202 | movq %r12,%r14 203 | orq %r11,%r12 204 | xorq %r13,%r12 205 | movq %r12,36(%rsi) 206 | 207 | andq %r9,%r13 208 | xorq %r8,%r13 209 | movq %r13,20(%rsi) 210 | 211 | orq %r8,%r9 212 | xorq %r14,%r9 213 | movq %r9,52(%rsi) 214 | 215 | andq %r14,%r8 216 | xorq %r11,%r8 217 | movq %r8,44(%rsi) 218 | 219 | 220 | xorq -84(%rdi),%rdx 221 | xorq -36(%rdi),%rbp 222 | rolq $62,%rdx 223 | xorq 68(%rdi),%rcx 224 | rolq $55,%rbp 225 | xorq 12(%rdi),%rax 226 | rolq $2,%rcx 227 | xorq 20(%rdi),%rbx 228 | xchgq %rsi,%rdi 229 | rolq $39,%rax 230 | rolq $41,%rbx 231 | movq %rdx,%r13 232 | andq %rbp,%rdx 233 | notq %rbp 234 | xorq %rcx,%rdx 235 | movq %rdx,92(%rdi) 236 | 237 | movq %rax,%r14 238 | andq %rbp,%rax 239 | xorq %r13,%rax 240 | movq %rax,60(%rdi) 241 | 242 | orq %rcx,%r13 243 | xorq %rbx,%r13 244 | movq %r13,84(%rdi) 245 | 246 | andq %rbx,%rcx 247 | xorq %r14,%rcx 248 | movq %rcx,76(%rdi) 249 | 250 | orq %r14,%rbx 251 | xorq %rbp,%rbx 252 | movq %rbx,68(%rdi) 253 | 254 | movq %rdx,%rbp 255 | movq %r13,%rdx 256 | 257 | testq $255,%r15 258 | jnz .Loop 259 | 260 | leaq -192(%r15),%r15 261 | .byte 0xf3,0xc3 262 | 263 | 264 | .globl KeccakF1600 265 | .def KeccakF1600; .scl 2; .type 32; .endef 266 | .p2align 5 267 | KeccakF1600: 268 | .byte 0xf3,0x0f,0x1e,0xfa 269 | movq %rdi,8(%rsp) 270 | movq %rsi,16(%rsp) 271 | movq %rsp,%r11 272 | .LSEH_begin_KeccakF1600: 273 | 274 | 275 | movq %rcx,%rdi 276 | pushq %rbx 277 | 278 | pushq %rbp 279 | 280 | pushq %r12 281 | 282 | pushq %r13 283 | 284 | pushq %r14 285 | 286 | pushq %r15 287 | 288 | 289 | leaq 100(%rdi),%rdi 290 | subq $200,%rsp 291 | 292 | .LSEH_body_KeccakF1600: 293 | 294 | 295 | notq -92(%rdi) 296 | notq -84(%rdi) 297 | notq -36(%rdi) 298 | notq -4(%rdi) 299 | notq 36(%rdi) 300 | notq 60(%rdi) 301 | 302 | leaq iotas(%rip),%r15 303 | leaq 100(%rsp),%rsi 304 | 305 | call __KeccakF1600 306 | 307 | notq -92(%rdi) 308 | notq -84(%rdi) 309 | notq -36(%rdi) 310 | notq -4(%rdi) 311 | notq 36(%rdi) 312 | notq 60(%rdi) 313 | leaq -100(%rdi),%rdi 314 | 315 | leaq 248(%rsp),%r11 316 | 317 | movq -48(%r11),%r15 318 | movq -40(%r11),%r14 319 | movq -32(%r11),%r13 320 | movq -24(%r11),%r12 321 | movq -16(%r11),%rbp 322 | movq -8(%r11),%rbx 323 | leaq (%r11),%rsp 324 | .LSEH_epilogue_KeccakF1600: 325 | mov 8(%r11),%rdi 326 | mov 16(%r11),%rsi 327 | 328 | .byte 0xf3,0xc3 329 | 330 | .LSEH_end_KeccakF1600: 331 | .globl SHA3_absorb 332 | .def SHA3_absorb; .scl 2; .type 32; .endef 333 | .p2align 5 334 | SHA3_absorb: 335 | .byte 0xf3,0x0f,0x1e,0xfa 336 | movq %rdi,8(%rsp) 337 | movq %rsi,16(%rsp) 338 | movq %rsp,%r11 339 | .LSEH_begin_SHA3_absorb: 340 | 341 | 342 | movq %rcx,%rdi 343 | movq %rdx,%rsi 344 | movq %r8,%rdx 345 | movq %r9,%rcx 346 | pushq %rbx 347 | 348 | pushq %rbp 349 | 350 | pushq %r12 351 | 352 | pushq %r13 353 | 354 | pushq %r14 355 | 356 | pushq %r15 357 | 358 | 359 | leaq 100(%rdi),%rdi 360 | subq $232,%rsp 361 | 362 | .LSEH_body_SHA3_absorb: 363 | 364 | 365 | movq %rsi,%r9 366 | leaq 100(%rsp),%rsi 367 | 368 | notq -92(%rdi) 369 | notq -84(%rdi) 370 | notq -36(%rdi) 371 | notq -4(%rdi) 372 | notq 36(%rdi) 373 | notq 60(%rdi) 374 | leaq iotas(%rip),%r15 375 | 376 | movq %rcx,216-100(%rsi) 377 | 378 | .Loop_absorb: 379 | cmpq %rcx,%rdx 380 | jc .Ldone_absorb 381 | 382 | shrq $3,%rcx 383 | leaq -100(%rdi),%r8 384 | 385 | .Lblock_absorb: 386 | movq (%r9),%rax 387 | leaq 8(%r9),%r9 388 | xorq (%r8),%rax 389 | leaq 8(%r8),%r8 390 | subq $8,%rdx 391 | movq %rax,-8(%r8) 392 | subq $1,%rcx 393 | jnz .Lblock_absorb 394 | 395 | movq %r9,200-100(%rsi) 396 | movq %rdx,208-100(%rsi) 397 | call __KeccakF1600 398 | movq 200-100(%rsi),%r9 399 | movq 208-100(%rsi),%rdx 400 | movq 216-100(%rsi),%rcx 401 | jmp .Loop_absorb 402 | 403 | .p2align 5 404 | .Ldone_absorb: 405 | movq %rdx,%rax 406 | 407 | notq -92(%rdi) 408 | notq -84(%rdi) 409 | notq -36(%rdi) 410 | notq -4(%rdi) 411 | notq 36(%rdi) 412 | notq 60(%rdi) 413 | 414 | leaq 280(%rsp),%r11 415 | 416 | movq -48(%r11),%r15 417 | movq -40(%r11),%r14 418 | movq -32(%r11),%r13 419 | movq -24(%r11),%r12 420 | movq -16(%r11),%rbp 421 | movq -8(%r11),%rbx 422 | leaq (%r11),%rsp 423 | .LSEH_epilogue_SHA3_absorb: 424 | mov 8(%r11),%rdi 425 | mov 16(%r11),%rsi 426 | 427 | .byte 0xf3,0xc3 428 | 429 | .LSEH_end_SHA3_absorb: 430 | .globl SHA3_squeeze 431 | .def SHA3_squeeze; .scl 2; .type 32; .endef 432 | .p2align 5 433 | SHA3_squeeze: 434 | .byte 0xf3,0x0f,0x1e,0xfa 435 | movq %rdi,8(%rsp) 436 | movq %rsi,16(%rsp) 437 | movq %rsp,%r11 438 | .LSEH_begin_SHA3_squeeze: 439 | 440 | 441 | movq %rcx,%rdi 442 | movq %rdx,%rsi 443 | movq %r8,%rdx 444 | movq %r9,%rcx 445 | pushq %r12 446 | 447 | pushq %r13 448 | 449 | pushq %r14 450 | 451 | subq $32,%rsp 452 | 453 | .LSEH_body_SHA3_squeeze: 454 | 455 | 456 | shrq $3,%rcx 457 | movq %rdi,%r8 458 | movq %rsi,%r12 459 | movq %rdx,%r13 460 | movq %rcx,%r14 461 | jmp .Loop_squeeze 462 | 463 | .p2align 5 464 | .Loop_squeeze: 465 | cmpq $8,%r13 466 | jb .Ltail_squeeze 467 | 468 | movq (%r8),%rax 469 | leaq 8(%r8),%r8 470 | movq %rax,(%r12) 471 | leaq 8(%r12),%r12 472 | subq $8,%r13 473 | jz .Ldone_squeeze 474 | 475 | subq $1,%rcx 476 | jnz .Loop_squeeze 477 | 478 | movq %rdi,%rcx 479 | call KeccakF1600 480 | movq %rdi,%r8 481 | movq %r14,%rcx 482 | jmp .Loop_squeeze 483 | 484 | .Ltail_squeeze: 485 | movq %r8,%rsi 486 | movq %r12,%rdi 487 | movq %r13,%rcx 488 | .byte 0xf3,0xa4 489 | 490 | .Ldone_squeeze: 491 | movq 32(%rsp),%r14 492 | movq 40(%rsp),%r13 493 | movq 48(%rsp),%r12 494 | addq $56,%rsp 495 | 496 | .LSEH_epilogue_SHA3_squeeze: 497 | mov 8(%rsp),%rdi 498 | mov 16(%rsp),%rsi 499 | 500 | .byte 0xf3,0xc3 501 | 502 | .LSEH_end_SHA3_squeeze: 503 | .p2align 8 504 | .quad 0,0,0,0,0,0,0,0 505 | 506 | iotas: 507 | .quad 0x0000000000000001 508 | .quad 0x0000000000008082 509 | .quad 0x800000000000808a 510 | .quad 0x8000000080008000 511 | .quad 0x000000000000808b 512 | .quad 0x0000000080000001 513 | .quad 0x8000000080008081 514 | .quad 0x8000000000008009 515 | .quad 0x000000000000008a 516 | .quad 0x0000000000000088 517 | .quad 0x0000000080008009 518 | .quad 0x000000008000000a 519 | .quad 0x000000008000808b 520 | .quad 0x800000000000008b 521 | .quad 0x8000000000008089 522 | .quad 0x8000000000008003 523 | .quad 0x8000000000008002 524 | .quad 0x8000000000000080 525 | .quad 0x000000000000800a 526 | .quad 0x800000008000000a 527 | .quad 0x8000000080008081 528 | .quad 0x8000000000008080 529 | .quad 0x0000000080000001 530 | .quad 0x8000000080008008 531 | 532 | .byte 75,101,99,99,97,107,45,49,54,48,48,32,97,98,115,111,114,98,32,97,110,100,32,115,113,117,101,101,122,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 533 | .section .pdata 534 | .p2align 2 535 | .rva .LSEH_begin_KeccakF1600 536 | .rva .LSEH_body_KeccakF1600 537 | .rva .LSEH_info_KeccakF1600_prologue 538 | 539 | .rva .LSEH_body_KeccakF1600 540 | .rva .LSEH_epilogue_KeccakF1600 541 | .rva .LSEH_info_KeccakF1600_body 542 | 543 | .rva .LSEH_epilogue_KeccakF1600 544 | .rva .LSEH_end_KeccakF1600 545 | .rva .LSEH_info_KeccakF1600_epilogue 546 | 547 | .rva .LSEH_begin_SHA3_absorb 548 | .rva .LSEH_body_SHA3_absorb 549 | .rva .LSEH_info_SHA3_absorb_prologue 550 | 551 | .rva .LSEH_body_SHA3_absorb 552 | .rva .LSEH_epilogue_SHA3_absorb 553 | .rva .LSEH_info_SHA3_absorb_body 554 | 555 | .rva .LSEH_epilogue_SHA3_absorb 556 | .rva .LSEH_end_SHA3_absorb 557 | .rva .LSEH_info_SHA3_absorb_epilogue 558 | 559 | .rva .LSEH_begin_SHA3_squeeze 560 | .rva .LSEH_body_SHA3_squeeze 561 | .rva .LSEH_info_SHA3_squeeze_prologue 562 | 563 | .rva .LSEH_body_SHA3_squeeze 564 | .rva .LSEH_epilogue_SHA3_squeeze 565 | .rva .LSEH_info_SHA3_squeeze_body 566 | 567 | .rva .LSEH_epilogue_SHA3_squeeze 568 | .rva .LSEH_end_SHA3_squeeze 569 | .rva .LSEH_info_SHA3_squeeze_epilogue 570 | 571 | .section .xdata 572 | .p2align 3 573 | .LSEH_info_KeccakF1600_prologue: 574 | .byte 1,0,5,0x0b 575 | .byte 0,0x74,1,0 576 | .byte 0,0x64,2,0 577 | .byte 0,0xb3 578 | .byte 0,0 579 | .long 0,0 580 | .LSEH_info_KeccakF1600_body: 581 | .byte 1,0,18,0 582 | .byte 0x00,0xf4,0x19,0x00 583 | .byte 0x00,0xe4,0x1a,0x00 584 | .byte 0x00,0xd4,0x1b,0x00 585 | .byte 0x00,0xc4,0x1c,0x00 586 | .byte 0x00,0x54,0x1d,0x00 587 | .byte 0x00,0x34,0x1e,0x00 588 | .byte 0x00,0x74,0x20,0x00 589 | .byte 0x00,0x64,0x21,0x00 590 | .byte 0x00,0x01,0x1f,0x00 591 | .byte 0x00,0x00,0x00,0x00 592 | .byte 0x00,0x00,0x00,0x00 593 | .LSEH_info_KeccakF1600_epilogue: 594 | .byte 1,0,5,11 595 | .byte 0x00,0x74,0x01,0x00 596 | .byte 0x00,0x64,0x02,0x00 597 | .byte 0x00,0xb3 598 | .byte 0x00,0x00,0x00,0x00,0x00,0x00 599 | .byte 0x00,0x00,0x00,0x00 600 | 601 | .LSEH_info_SHA3_absorb_prologue: 602 | .byte 1,0,5,0x0b 603 | .byte 0,0x74,1,0 604 | .byte 0,0x64,2,0 605 | .byte 0,0xb3 606 | .byte 0,0 607 | .long 0,0 608 | .LSEH_info_SHA3_absorb_body: 609 | .byte 1,0,18,0 610 | .byte 0x00,0xf4,0x1d,0x00 611 | .byte 0x00,0xe4,0x1e,0x00 612 | .byte 0x00,0xd4,0x1f,0x00 613 | .byte 0x00,0xc4,0x20,0x00 614 | .byte 0x00,0x54,0x21,0x00 615 | .byte 0x00,0x34,0x22,0x00 616 | .byte 0x00,0x74,0x24,0x00 617 | .byte 0x00,0x64,0x25,0x00 618 | .byte 0x00,0x01,0x23,0x00 619 | .byte 0x00,0x00,0x00,0x00 620 | .byte 0x00,0x00,0x00,0x00 621 | .LSEH_info_SHA3_absorb_epilogue: 622 | .byte 1,0,5,11 623 | .byte 0x00,0x74,0x01,0x00 624 | .byte 0x00,0x64,0x02,0x00 625 | .byte 0x00,0xb3 626 | .byte 0x00,0x00,0x00,0x00,0x00,0x00 627 | .byte 0x00,0x00,0x00,0x00 628 | 629 | .LSEH_info_SHA3_squeeze_prologue: 630 | .byte 1,0,5,0x0b 631 | .byte 0,0x74,1,0 632 | .byte 0,0x64,2,0 633 | .byte 0,0xb3 634 | .byte 0,0 635 | .long 0,0 636 | .LSEH_info_SHA3_squeeze_body: 637 | .byte 1,0,11,0 638 | .byte 0x00,0xe4,0x04,0x00 639 | .byte 0x00,0xd4,0x05,0x00 640 | .byte 0x00,0xc4,0x06,0x00 641 | .byte 0x00,0x74,0x08,0x00 642 | .byte 0x00,0x64,0x09,0x00 643 | .byte 0x00,0x62 644 | .byte 0x00,0x00,0x00,0x00,0x00,0x00 645 | .LSEH_info_SHA3_squeeze_epilogue: 646 | .byte 1,0,4,0 647 | .byte 0x00,0x74,0x01,0x00 648 | .byte 0x00,0x64,0x02,0x00 649 | .byte 0x00,0x00,0x00,0x00 650 | 651 | -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | use crate::Error; 2 | use clap::{ArgGroup, Parser}; 3 | use log::LevelFilter; 4 | use std::{net::IpAddr, str::FromStr}; 5 | 6 | #[derive(Debug, Parser)] 7 | #[clap(about, version, author)] 8 | #[clap(group(ArgGroup::new("required")))] 9 | pub struct Opt { 10 | #[clap(short, long, display_order = 3)] 11 | /// Enable debug logging level 12 | pub debug: bool, 13 | #[clap(short = 'a', long = "mining-address", display_order = 0)] 14 | /// The Spectre address for the miner reward 15 | pub mining_address: String, 16 | #[clap(short = 's', long = "spectred-address", default_value = "127.0.0.1", display_order = 1)] 17 | /// The IP of the spectred instance 18 | pub spectred_address: String, 19 | 20 | #[clap(long = "devfund", display_order = 6)] 21 | /// Mine a percentage of the blocks to the Spectre devfund [default: Off] 22 | pub devfund_address: Option, 23 | 24 | #[clap(long = "devfund-percent", default_value = "1", display_order = 7, value_parser = parse_devfund_percent)] 25 | /// The percentage of blocks to send to the devfund 26 | pub devfund_percent: u16, 27 | 28 | #[clap(short, long, display_order = 2)] 29 | /// Spectred port [default: Mainnet = 18110, Testnet = 18210] 30 | port: Option, 31 | 32 | #[clap(long, display_order = 4)] 33 | /// Use testnet instead of mainnet [default: false] 34 | testnet: bool, 35 | #[clap(short = 't', long = "threads", display_order = 5)] 36 | /// Amount of miner threads to launch [default: number of logical cpus] 37 | pub num_threads: Option, 38 | #[clap(long = "mine-when-not-synced", display_order = 8)] 39 | /// Mine even when spectred says it is not synced, only useful when passing `--allow-submit-block-when-not-synced` to spectred [default: false] 40 | pub mine_when_not_synced: bool, 41 | #[clap(long = "throttle", display_order = 9)] 42 | /// Throttle (milliseconds) between each pow hash generation (used for development testing) 43 | pub throttle: Option, 44 | #[clap(long, display_order = 10)] 45 | /// Output logs in alternative format (same as spectred) 46 | pub altlogs: bool, 47 | } 48 | 49 | fn parse_devfund_percent(s: &str) -> Result { 50 | let err = "devfund-percent should be --devfund-percent=XX.YY up to 2 numbers after the dot"; 51 | let mut splited = s.split('.'); 52 | let prefix = splited.next().ok_or(err)?; 53 | // if there's no postfix then it's 0. 54 | let postfix = splited.next().ok_or(err).unwrap_or("0"); 55 | // error if there's more than a single dot 56 | if splited.next().is_some() { 57 | return Err(err); 58 | }; 59 | // error if there are more than 2 numbers before or after the dot 60 | if prefix.len() > 2 || postfix.len() > 2 { 61 | return Err(err); 62 | } 63 | let postfix: u16 = postfix.parse().map_err(|_| err)?; 64 | let prefix: u16 = prefix.parse().map_err(|_| err)?; 65 | // can't be more than 99.99%, 66 | if prefix >= 100 || postfix >= 100 { 67 | return Err(err); 68 | } 69 | Ok(prefix * 100 + postfix) 70 | } 71 | 72 | impl Opt { 73 | pub fn process(&mut self) -> Result<(), Error> { 74 | if self.spectred_address.is_empty() { 75 | self.spectred_address = "127.0.0.1".to_string(); 76 | } 77 | 78 | if !self.spectred_address.starts_with("grpc://") { 79 | IpAddr::from_str(&self.spectred_address)?; 80 | let port = self.port(); 81 | self.spectred_address = format!("grpc://{}:{}", self.spectred_address, port); 82 | } 83 | log::info!("Spectred address: {}", self.spectred_address); 84 | 85 | Ok(()) 86 | } 87 | 88 | fn port(&mut self) -> u16 { 89 | *self.port.get_or_insert(if self.testnet { 18210 } else { 18110 }) 90 | } 91 | 92 | pub fn log_level(&self) -> LevelFilter { 93 | if self.debug { 94 | LevelFilter::Debug 95 | } else { 96 | LevelFilter::Info 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | miner::MinerManager, 3 | proto::{ 4 | rpc_client::RpcClient, spectred_message::Payload, GetBlockTemplateRequestMessage, GetInfoRequestMessage, 5 | SpectredMessage, 6 | }, 7 | Error, ShutdownHandler, 8 | }; 9 | use log::{error, info, warn}; 10 | use tokio::sync::mpsc::{self, error::SendError, Sender}; 11 | use tokio_stream::wrappers::ReceiverStream; 12 | use tonic::{transport::Channel as TonicChannel, Streaming}; 13 | 14 | static EXTRA_DATA: &str = concat!(env!("CARGO_PKG_VERSION")); 15 | 16 | #[allow(dead_code)] 17 | pub struct SpectredHandler { 18 | client: RpcClient, 19 | pub send_channel: Sender, 20 | stream: Streaming, 21 | miner_address: String, 22 | mine_when_not_synced: bool, 23 | devfund_address: Option, 24 | devfund_percent: u16, 25 | block_template_ctr: u64, 26 | } 27 | 28 | impl SpectredHandler { 29 | pub async fn connect(address: D, miner_address: String, mine_when_not_synced: bool) -> Result 30 | where 31 | D: TryInto, 32 | D::Error: Into, 33 | { 34 | let mut client = RpcClient::connect(address).await?; 35 | let (send_channel, recv) = mpsc::channel(3); 36 | send_channel.send(GetInfoRequestMessage {}.into()).await?; 37 | send_channel 38 | .send( 39 | GetBlockTemplateRequestMessage { pay_address: miner_address.clone(), extra_data: EXTRA_DATA.into() } 40 | .into(), 41 | ) 42 | .await?; 43 | let stream = client.message_stream(ReceiverStream::new(recv)).await?.into_inner(); 44 | Ok(Self { 45 | client, 46 | stream, 47 | send_channel, 48 | miner_address, 49 | mine_when_not_synced, 50 | devfund_address: None, 51 | devfund_percent: 0, 52 | block_template_ctr: 0, 53 | }) 54 | } 55 | 56 | pub fn add_devfund(&mut self, address: String, percent: u16) { 57 | self.devfund_address = Some(address); 58 | self.devfund_percent = percent; 59 | } 60 | 61 | pub async fn client_send(&self, msg: impl Into) -> Result<(), SendError> { 62 | self.send_channel.send(msg.into()).await 63 | } 64 | 65 | pub async fn client_get_block_template(&mut self) -> Result<(), SendError> { 66 | let pay_address = match &self.devfund_address { 67 | Some(devfund_address) if (self.block_template_ctr % 10_000) as u16 <= self.devfund_percent => { 68 | devfund_address.clone() 69 | } 70 | _ => self.miner_address.clone(), 71 | }; 72 | self.block_template_ctr += 1; 73 | self.client_send(GetBlockTemplateRequestMessage { pay_address, extra_data: EXTRA_DATA.into() }).await 74 | } 75 | 76 | pub async fn listen(&mut self, miner: &mut MinerManager, shutdown: ShutdownHandler) -> Result<(), Error> { 77 | while let Some(msg) = self.stream.message().await? { 78 | if shutdown.is_shutdown() { 79 | break; 80 | } 81 | match msg.payload { 82 | Some(payload) => self.handle_message(payload, miner).await?, 83 | None => warn!("spectred message payload is empty"), 84 | } 85 | } 86 | Ok(()) 87 | } 88 | 89 | async fn handle_message(&mut self, msg: Payload, miner: &mut MinerManager) -> Result<(), Error> { 90 | match msg { 91 | Payload::NewBlockTemplateNotification(_) => self.client_get_block_template().await?, 92 | Payload::GetBlockTemplateResponse(template) => match (template.block, template.is_synced, template.error) { 93 | (Some(b), true, None) => miner.process_block(Some(b))?, 94 | (Some(b), false, None) if self.mine_when_not_synced => miner.process_block(Some(b))?, 95 | (_, false, None) => miner.process_block(None)?, 96 | (_, _, Some(e)) => warn!("GetTemplate returned with an error: {:?}", e), 97 | (None, true, None) => error!("No block and No Error!"), 98 | }, 99 | Payload::SubmitBlockResponse(res) => match res.error { 100 | None => info!("Block submitted successfully!"), 101 | Some(e) => warn!("Failed submitting block: {:?}", e), 102 | }, 103 | Payload::GetBlockResponse(msg) => { 104 | if let Some(e) = msg.error { 105 | return Err(e.message.into()); 106 | } 107 | info!("Get block response: {:?}", msg); 108 | } 109 | Payload::GetInfoResponse(info) => info!("Spectred version: {}", info.server_version), 110 | Payload::NotifyNewBlockTemplateResponse(res) => match res.error { 111 | None => info!("Registered for new template notifications"), 112 | Some(e) => error!("Failed registering for new template notifications: {:?}", e), 113 | }, 114 | msg => info!("Got unknown msg: {:?}", msg), 115 | } 116 | Ok(()) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(all(test, feature = "bench"), feature(test))] 2 | 3 | use chrono::Local; 4 | use clap::Parser; 5 | use log::{info, warn}; 6 | use std::error::Error as StdError; 7 | use std::{ 8 | io::Write, 9 | sync::{ 10 | atomic::{AtomicBool, Ordering}, 11 | Arc, 12 | }, 13 | time::Duration, 14 | }; 15 | 16 | // Add sysinfo crate for system information 17 | use sysinfo::System; 18 | 19 | use crate::{ 20 | cli::Opt, client::SpectredHandler, miner::MinerManager, proto::NotifyNewBlockTemplateRequestMessage, 21 | target::Uint256, 22 | }; 23 | 24 | mod cli; 25 | mod client; 26 | mod miner; 27 | mod pow; 28 | mod spectred_messages; 29 | mod swap_rust; 30 | mod target; 31 | 32 | pub mod proto { 33 | #![allow(clippy::derive_partial_eq_without_eq)] 34 | tonic::include_proto!("protowire"); 35 | } 36 | 37 | pub type Error = Box; 38 | 39 | type Hash = Uint256; 40 | 41 | #[derive(Debug, Clone)] 42 | pub struct ShutdownHandler(Arc); 43 | 44 | pub struct ShutdownOnDrop(ShutdownHandler); 45 | 46 | impl ShutdownHandler { 47 | #[inline(always)] 48 | pub fn is_shutdown(&self) -> bool { 49 | self.0.load(Ordering::Acquire) 50 | } 51 | 52 | #[inline(always)] 53 | pub fn arm(&self) -> ShutdownOnDrop { 54 | ShutdownOnDrop(self.clone()) 55 | } 56 | } 57 | 58 | impl Drop for ShutdownOnDrop { 59 | fn drop(&mut self) { 60 | self.0 .0.store(true, Ordering::Release); 61 | } 62 | } 63 | 64 | #[tokio::main] 65 | async fn main() -> Result<(), Error> { 66 | let mut opt: Opt = Opt::parse(); 67 | opt.process()?; 68 | 69 | // Create a System object to get system information 70 | let mut sys = System::new_all(); 71 | sys.refresh_all(); 72 | 73 | // Display system information 74 | println!("=> System Information:"); 75 | println!("System name: {}", System::name().unwrap_or("Unknown".to_string())); 76 | println!("System kernel version: {}", System::kernel_version().unwrap_or("Unknown".to_string())); 77 | println!("System OS version: {}", System::os_version().unwrap_or("Unknown".to_string())); 78 | println!("System host name: {}", System::host_name().unwrap_or("Unknown".to_string())); 79 | 80 | // Display CPU brand and frequency information only if there is a change 81 | let mut last_cpu_brand = String::new(); 82 | let mut last_cpu_frequency = 0; 83 | for cpu in sys.cpus() { 84 | if cpu.brand() != last_cpu_brand { 85 | println!("CPU brand: {}", cpu.brand()); 86 | last_cpu_brand = cpu.brand().to_string(); 87 | } 88 | if cpu.frequency() != last_cpu_frequency { 89 | println!("CPU Frequency: {} MHz", cpu.frequency()); 90 | last_cpu_frequency = cpu.frequency(); 91 | } 92 | } 93 | 94 | // Display number of CPUs 95 | println!("Number of CPUs: {}", sys.cpus().len()); 96 | let total_memory_gb = sys.total_memory() as f64 / 1_073_741_824.0; 97 | println!("Total RAM: {:.2} GB", total_memory_gb); 98 | 99 | let mut builder = env_logger::builder(); 100 | builder.filter_level(opt.log_level()).parse_default_env(); 101 | if opt.altlogs { 102 | builder.format(|buf, record| { 103 | let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S%.3f%:z"); 104 | writeln!(buf, "{} [{:>5}] {}", timestamp, record.level(), record.args()) 105 | }); 106 | } 107 | builder.init(); 108 | 109 | let throttle = opt.throttle.map(Duration::from_millis); 110 | let shutdown = ShutdownHandler(Arc::new(AtomicBool::new(false))); 111 | let _shutdown_when_dropped = shutdown.arm(); 112 | 113 | while !shutdown.is_shutdown() { 114 | match SpectredHandler::connect( 115 | opt.spectred_address.clone(), 116 | opt.mining_address.clone(), 117 | opt.mine_when_not_synced, 118 | ) 119 | .await 120 | { 121 | Ok(mut client) => { 122 | let mut miner_manager = 123 | MinerManager::new(client.send_channel.clone(), opt.num_threads, throttle, shutdown.clone()); 124 | if let Some(devfund_address) = &opt.devfund_address { 125 | client.add_devfund(devfund_address.clone(), opt.devfund_percent); 126 | info!( 127 | "devfund enabled, mining {}.{}% of the time to devfund address: {} ", 128 | opt.devfund_percent / 100, 129 | opt.devfund_percent % 100, 130 | devfund_address 131 | ); 132 | } 133 | if let Err(e) = client.client_send(NotifyNewBlockTemplateRequestMessage {}).await { 134 | warn!("Error sending block template request: {}", e); 135 | } 136 | if let Err(e) = client.client_get_block_template().await { 137 | warn!("Error getting block template: {}", e); 138 | } 139 | if let Err(e) = client.listen(&mut miner_manager, shutdown.clone()).await { 140 | warn!("Disconnected from spectred: {}. Retrying", e); 141 | } 142 | } 143 | Err(e) => { 144 | warn!("Failed to connect to spectred: {}. Retrying in 10 seconds...", e); 145 | } 146 | } 147 | tokio::time::sleep(Duration::from_secs(10)).await; 148 | } 149 | Ok(()) 150 | } 151 | -------------------------------------------------------------------------------- /src/miner.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | pow, 3 | proto::{RpcBlock, SpectredMessage}, 4 | swap_rust::WatchSwap, 5 | Error, ShutdownHandler, 6 | }; 7 | use log::{info, warn}; 8 | use rand::{thread_rng, RngCore}; 9 | use std::{ 10 | num::Wrapping, 11 | sync::{ 12 | atomic::{AtomicU64, AtomicUsize, Ordering}, 13 | Arc, 14 | }, 15 | time::Duration, 16 | }; 17 | use tokio::{ 18 | sync::mpsc::Sender, 19 | task::{self, JoinHandle}, 20 | time::MissedTickBehavior, 21 | }; 22 | 23 | type MinerHandler = std::thread::JoinHandle>; 24 | 25 | #[allow(dead_code)] 26 | pub struct MinerManager { 27 | handles: Vec, 28 | block_channel: WatchSwap, 29 | send_channel: Sender, 30 | logger_handle: JoinHandle<()>, 31 | is_synced: bool, 32 | hashes_tried: Arc, 33 | current_state_id: AtomicUsize, 34 | } 35 | 36 | impl Drop for MinerManager { 37 | fn drop(&mut self) { 38 | self.logger_handle.abort(); 39 | } 40 | } 41 | 42 | pub fn get_num_cpus(n_cpus: Option) -> u16 { 43 | n_cpus.unwrap_or_else(|| { 44 | num_cpus::get_physical().try_into().expect("Doesn't make sense to have more than 65,536 CPU cores") 45 | }) 46 | } 47 | 48 | const LOG_RATE: Duration = Duration::from_secs(10); 49 | 50 | impl MinerManager { 51 | pub fn new( 52 | send_channel: Sender, 53 | n_cpus: Option, 54 | throttle: Option, 55 | shutdown: ShutdownHandler, 56 | ) -> Self { 57 | let hashes_tried = Arc::new(AtomicU64::new(0)); 58 | let watch = WatchSwap::empty(); 59 | let handles = Self::launch_cpu_threads( 60 | send_channel.clone(), 61 | hashes_tried.clone(), 62 | watch.clone(), 63 | shutdown, 64 | n_cpus, 65 | throttle, 66 | ) 67 | .collect(); 68 | 69 | Self { 70 | handles, 71 | block_channel: watch, 72 | send_channel, 73 | logger_handle: task::spawn(Self::log_hashrate(Arc::clone(&hashes_tried))), 74 | is_synced: true, 75 | hashes_tried, 76 | current_state_id: AtomicUsize::new(0), 77 | } 78 | } 79 | 80 | fn launch_cpu_threads( 81 | send_channel: Sender, 82 | hashes_tried: Arc, 83 | work_channel: WatchSwap, 84 | shutdown: ShutdownHandler, 85 | n_cpus: Option, 86 | throttle: Option, 87 | ) -> impl Iterator { 88 | let n_cpus = get_num_cpus(n_cpus); 89 | info!("Launching: {} cpu miners", n_cpus); 90 | (0..n_cpus).map(move |_| { 91 | Self::launch_cpu_miner( 92 | send_channel.clone(), 93 | work_channel.clone(), 94 | hashes_tried.clone(), 95 | throttle, 96 | shutdown.clone(), 97 | ) 98 | }) 99 | } 100 | 101 | pub fn process_block(&mut self, block: Option) -> Result<(), Error> { 102 | let state = if let Some(b) = block { 103 | self.is_synced = true; 104 | // Relaxed ordering here means there's no promise that the counter will always go up, but the id will always be unique 105 | let id = self.current_state_id.fetch_add(1, Ordering::Relaxed); 106 | Some(pow::State::new(id, b)?) 107 | } else { 108 | if !self.is_synced { 109 | return Ok(()); 110 | } 111 | self.is_synced = false; 112 | warn!("Spectred is not synced, skipping current template"); 113 | None 114 | }; 115 | 116 | self.block_channel.swap(state); 117 | Ok(()) 118 | } 119 | 120 | pub fn launch_cpu_miner( 121 | send_channel: Sender, 122 | mut block_channel: WatchSwap, 123 | hashes_tried: Arc, 124 | throttle: Option, 125 | shutdown: ShutdownHandler, 126 | ) -> MinerHandler { 127 | // We mark it cold as the function is not called often, and it's not in the hot path 128 | #[cold] 129 | fn found_block(send_channel: &Sender, block: RpcBlock) -> Result<(), Error> { 130 | let block_hash = block.block_hash().expect("We just got it from the state, we should be able to hash it"); 131 | send_channel.blocking_send(SpectredMessage::submit_block(block))?; 132 | info!("Found a block: {:x}", block_hash); 133 | Ok(()) 134 | } 135 | 136 | let mut nonce = Wrapping(thread_rng().next_u64()); 137 | std::thread::spawn(move || { 138 | let mut state = None; 139 | loop { 140 | if state.is_none() { 141 | state = block_channel.wait_for_change().as_deref().cloned(); 142 | } 143 | let Some(state_ref) = state.as_mut() else { 144 | continue; 145 | }; 146 | state_ref.nonce = nonce.0; 147 | 148 | if let Some(block) = state_ref.generate_block_if_pow() { 149 | found_block(&send_channel, block)?; 150 | } 151 | nonce += Wrapping(1); 152 | 153 | if nonce.0 % 128 == 0 { 154 | hashes_tried.fetch_add(128, Ordering::Relaxed); 155 | if shutdown.is_shutdown() { 156 | return Ok(()); 157 | } 158 | if let Some(new_state) = block_channel.get_changed() { 159 | state = new_state.as_deref().cloned(); 160 | } 161 | } 162 | 163 | if let Some(sleep_duration) = throttle { 164 | std::thread::sleep(sleep_duration) 165 | } 166 | } 167 | }) 168 | } 169 | 170 | async fn log_hashrate(hashes_tried: Arc) { 171 | let mut ticker = tokio::time::interval(LOG_RATE); 172 | ticker.set_missed_tick_behavior(MissedTickBehavior::Delay); 173 | let mut last_instant = ticker.tick().await; 174 | for i in 0u64.. { 175 | let now = ticker.tick().await; 176 | let hashes = hashes_tried.swap(0, Ordering::Relaxed); 177 | let rate = (hashes as f64) / (now - last_instant).as_secs_f64(); 178 | if hashes == 0 && i % 2 == 0 { 179 | warn!("Spectred is still not synced"); 180 | } else if hashes != 0 { 181 | let (rate, suffix) = Self::hash_suffix(rate); 182 | info!("Current hashrate is: {:.2} {}", rate, suffix); 183 | } 184 | last_instant = now; 185 | } 186 | } 187 | 188 | #[inline] 189 | fn hash_suffix(n: f64) -> (f64, &'static str) { 190 | match n { 191 | n if n < 1_000.0 => (n, "hash/s"), 192 | n if n < 1_000_000.0 => (n / 1_000.0, "Khash/s"), 193 | n if n < 1_000_000_000.0 => (n / 1_000_000.0, "Mhash/s"), 194 | n if n < 1_000_000_000_000.0 => (n / 1_000_000_000.0, "Ghash/s"), 195 | n if n < 1_000_000_000_000_000.0 => (n / 1_000_000_000_000.0, "Thash/s"), 196 | _ => (n, "hash/s"), 197 | } 198 | } 199 | } 200 | 201 | #[cfg(all(test, feature = "bench"))] 202 | mod benches { 203 | extern crate test; 204 | 205 | use self::test::{black_box, Bencher}; 206 | use crate::pow::State; 207 | use crate::proto::{RpcBlock, RpcBlockHeader}; 208 | use rand::{thread_rng, RngCore}; 209 | 210 | #[bench] 211 | pub fn bench_mining(bh: &mut Bencher) { 212 | let mut state = State::new( 213 | 1, 214 | RpcBlock { 215 | header: Some(RpcBlockHeader { 216 | version: 1, 217 | parents: vec![], 218 | hash_merkle_root: "23618af45051560529440541e7dc56be27676d278b1e00324b048d410a19d764".to_string(), 219 | accepted_id_merkle_root: "947d1a10378d6478b6957a0ed71866812dee33684968031b1cace4908c149d94" 220 | .to_string(), 221 | utxo_commitment: "ec5e8fc0bc0c637004cee262cef12e7cf6d9cd7772513dbd466176a07ab7c4f4".to_string(), 222 | timestamp: 654654353, 223 | bits: 0x1e7fffff, 224 | nonce: 0, 225 | daa_score: 654456, 226 | blue_work: "d8e28a03234786".to_string(), 227 | pruning_point: "be4c415d378f9113fabd3c09fcc84ddb6a00f900c87cb6a1186993ddc3014e2d".to_string(), 228 | blue_score: 1164419, 229 | }), 230 | transactions: vec![], 231 | verbose_data: None, 232 | }, 233 | ) 234 | .unwrap(); 235 | state.nonce = thread_rng().next_u64(); 236 | bh.iter(|| { 237 | for _ in 0..100 { 238 | black_box(state.check_pow()); 239 | state.nonce += 1; 240 | } 241 | }); 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /src/pow.rs: -------------------------------------------------------------------------------- 1 | pub use crate::pow::hasher::HeaderHasher; 2 | use crate::{ 3 | pow::{ 4 | hasher::{Hasher, PowHasher}, 5 | heavy_hash::Matrix, 6 | }, 7 | proto::{RpcBlock, RpcBlockHeader}, 8 | target::{self, Uint256}, 9 | Error, 10 | }; 11 | use spectrex::astrobwtv3; 12 | 13 | mod hasher; 14 | mod heavy_hash; 15 | mod keccak; 16 | mod xoshiro; 17 | 18 | #[derive(Clone)] 19 | pub struct State { 20 | #[allow(dead_code)] 21 | pub id: usize, 22 | matrix: Matrix, 23 | pub nonce: u64, 24 | target: Uint256, 25 | block: RpcBlock, 26 | // PRE_POW_HASH || TIME || 32 zero byte padding; without NONCE 27 | hasher: PowHasher, 28 | } 29 | 30 | impl State { 31 | #[inline] 32 | pub fn new(id: usize, block: RpcBlock) -> Result { 33 | let header = &block.header.as_ref().ok_or("Header is missing")?; 34 | 35 | let target = target::u256_from_compact_target(header.bits); 36 | let mut hasher = HeaderHasher::new(); 37 | serialize_header(&mut hasher, header, true); 38 | let pre_pow_hash = hasher.finalize(); 39 | // PRE_POW_HASH || TIME || 32 zero byte padding || NONCE 40 | let hasher = PowHasher::new(pre_pow_hash, header.timestamp as u64); 41 | let matrix = Matrix::generate(pre_pow_hash); 42 | 43 | Ok(Self { id, matrix, nonce: 0, target, block, hasher }) 44 | } 45 | 46 | #[inline(always)] 47 | // PRE_POW_HASH || TIME || 32 zero byte padding || NONCE 48 | pub fn calculate_pow(&self) -> Uint256 { 49 | // Hasher already contains PRE_POW_HASH || TIME || 32 zero byte padding; so only the NONCE is missing 50 | let hash = self.hasher.finalize_with_nonce(self.nonce); 51 | let bwt_hash = astrobwtv3::astrobwtv3_hash(&hash.to_le_bytes()); 52 | self.matrix.heavy_hash(Uint256::from_le_bytes(bwt_hash)) 53 | } 54 | 55 | #[inline(always)] 56 | pub fn check_pow(&self) -> bool { 57 | let pow = self.calculate_pow(); 58 | // The pow hash must be less or equal than the claimed target. 59 | pow <= self.target 60 | } 61 | 62 | #[inline(always)] 63 | pub fn generate_block_if_pow(&self) -> Option { 64 | self.check_pow().then(|| { 65 | let mut block = self.block.clone(); 66 | let header = block.header.as_mut().expect("We checked that a header exists on creation"); 67 | header.nonce = self.nonce; 68 | block 69 | }) 70 | } 71 | } 72 | 73 | #[cfg(not(any(target_pointer_width = "64", target_pointer_width = "32")))] 74 | compile_error!("Supporting only 32/64 bits"); 75 | 76 | #[inline(always)] 77 | pub fn serialize_header(hasher: &mut H, header: &RpcBlockHeader, for_pre_pow: bool) { 78 | let (nonce, timestamp) = if for_pre_pow { (0, 0) } else { (header.nonce, header.timestamp) }; 79 | let num_parents = header.parents.len(); 80 | let version: u16 = header.version.try_into().unwrap(); 81 | hasher.update(version.to_le_bytes()).update((num_parents as u64).to_le_bytes()); 82 | 83 | let mut hash = [0u8; 32]; 84 | for parent in &header.parents { 85 | hasher.update((parent.parent_hashes.len() as u64).to_le_bytes()); 86 | for hash_string in &parent.parent_hashes { 87 | decode_to_slice(hash_string, &mut hash).unwrap(); 88 | hasher.update(hash); 89 | } 90 | } 91 | decode_to_slice(&header.hash_merkle_root, &mut hash).unwrap(); 92 | hasher.update(hash); 93 | 94 | decode_to_slice(&header.accepted_id_merkle_root, &mut hash).unwrap(); 95 | hasher.update(hash); 96 | decode_to_slice(&header.utxo_commitment, &mut hash).unwrap(); 97 | hasher.update(hash); 98 | 99 | hasher 100 | .update(timestamp.to_le_bytes()) 101 | .update(header.bits.to_le_bytes()) 102 | .update(nonce.to_le_bytes()) 103 | .update(header.daa_score.to_le_bytes()) 104 | .update(header.blue_score.to_le_bytes()); 105 | 106 | // I'm assuming here BlueWork will never pass 256 bits. 107 | let blue_work_len = (header.blue_work.len() + 1) / 2; 108 | if header.blue_work.len() % 2 == 0 { 109 | decode_to_slice(&header.blue_work, &mut hash[..blue_work_len]).unwrap(); 110 | } else { 111 | let mut blue_work = String::with_capacity(header.blue_work.len() + 1); 112 | blue_work.push('0'); 113 | blue_work.push_str(&header.blue_work); 114 | decode_to_slice(&blue_work, &mut hash[..blue_work_len]).unwrap(); 115 | } 116 | 117 | hasher.update((blue_work_len as u64).to_le_bytes()).update(&hash[..blue_work_len]); 118 | 119 | decode_to_slice(&header.pruning_point, &mut hash).unwrap(); 120 | hasher.update(hash); 121 | } 122 | 123 | #[allow(dead_code)] // False Positive: https://github.com/rust-lang/rust/issues/88900 124 | #[derive(Debug)] 125 | enum FromHexError { 126 | OddLength, 127 | InvalidStringLength, 128 | InvalidHexCharacter { c: char, index: usize }, 129 | } 130 | 131 | #[inline(always)] 132 | fn decode_to_slice>(data: T, out: &mut [u8]) -> Result<(), FromHexError> { 133 | let data = data.as_ref(); 134 | if data.len() % 2 != 0 { 135 | return Err(FromHexError::OddLength); 136 | } 137 | if data.len() / 2 != out.len() { 138 | return Err(FromHexError::InvalidStringLength); 139 | } 140 | 141 | for (i, byte) in out.iter_mut().enumerate() { 142 | *byte = val(data[2 * i], 2 * i)? << 4 | val(data[2 * i + 1], 2 * i + 1)?; 143 | } 144 | 145 | #[inline(always)] 146 | fn val(c: u8, idx: usize) -> Result { 147 | match c { 148 | b'A'..=b'F' => Ok(c - b'A' + 10), 149 | b'a'..=b'f' => Ok(c - b'a' + 10), 150 | b'0'..=b'9' => Ok(c - b'0'), 151 | _ => Err(FromHexError::InvalidHexCharacter { c: c as char, index: idx }), 152 | } 153 | } 154 | 155 | Ok(()) 156 | } 157 | 158 | #[cfg(test)] 159 | mod tests { 160 | use crate::pow::hasher::{Hasher, HeaderHasher}; 161 | use crate::pow::serialize_header; 162 | use crate::proto::{RpcBlockHeader, RpcBlockLevelParents}; 163 | use crate::Hash; 164 | 165 | struct Buf(Vec); 166 | impl Hasher for Buf { 167 | fn update>(&mut self, data: A) -> &mut Self { 168 | self.0.extend(data.as_ref()); 169 | self 170 | } 171 | } 172 | 173 | #[test] 174 | fn test_serialize_header() { 175 | let header = RpcBlockHeader { 176 | version: 24565, 177 | parents: vec![ 178 | RpcBlockLevelParents { 179 | parent_hashes: vec![ 180 | "62a5eee82abdf44a2d0b75fb180daf48a79ee0b10d394651850fd4a178892ee2".into(), 181 | "85ece1511455780875d64ee2d3d0d0de6bf8f9b44ce85ff044c6b1f83b8e883b".into(), 182 | "bf857aab99c5b252c7429c32f3a8aeb79ef856f659c18f0dcecc77c75e7a81bf".into(), 183 | "de275f67cfe242cf3cc354f3ede2d6becc4ea3ae5e88526a9f4a578bcb9ef2d4".into(), 184 | "a65314768d6d299761ea9e4f5aa6aec3fc78c6aae081ac8120c720efcd6cea84".into(), 185 | "b6925e607be063716f96ddcdd01d75045c3f000f8a796bce6c512c3801aacaee".into(), 186 | ], 187 | }, 188 | RpcBlockLevelParents { 189 | parent_hashes: vec![ 190 | "dfad5b50ece0b8b7c1965d9181251b7c9c9ca5205afc16a236a2efcdd2d12d2a".into(), 191 | "79d074a8280ae9439eb0d6aeca0823ae02d67d866ac2c4fe4a725053da119b9d".into(), 192 | "4f515140a2d7239c40b45ac3950d941fc4fe1c0cb96ad322d62282295fbfe11e".into(), 193 | "26a433076db5c1444c3a34d32a5c4a7ffbe8d181f7ed3b8cfe904f93f8f06d29".into(), 194 | "bcd9ed847b182e046410f44bc4b0f3f03a0d06820a30f257f8114130678ac045".into(), 195 | "86c1e3c9342c8b8055c466d886441d259906d69acd894b968ae9f0eb9d965ce6".into(), 196 | "a4693c4ebe881501b7d9846b66eb02b57e5cda7b6cba6891d616bd686c37b834".into(), 197 | ], 198 | }, 199 | RpcBlockLevelParents { 200 | parent_hashes: vec![ 201 | "613ac8ba52734ae4e3f1217acd5f83270814301867b5d06711b238001c7957b2".into(), 202 | "7719ce3f3188dfe57deebf6f82595a10f7bb562ca04d5c3d27942958c6db3262".into(), 203 | "670649f3bc97d9a2316735ede682a5dfe6f1a011fbc98ad0fbe790003c01e8e9".into(), 204 | "967703af665e9f72407f4b03d4fdb474aafe8a0d3e0515dd4650cf51172b8124".into(), 205 | "8bcb7f969e400b6c5b127768b1c412fae98cf57631cf37033b4b4aba7d7ed319".into(), 206 | "ba147249c908ac70d1c406dade0e828eb6ba0dcaa88285543e10213c643fc860".into(), 207 | "3b5860236670babcad0bd7f4c4190e323623a868d1eae1769f40a26631431b3b".into(), 208 | "d5215605d2086fead499ac63a4653d12283d56019c3795a98a126d09cfcbe36c".into(), 209 | "dcc93788a5409f8b6e42c2dd83aa46611852ad0b5028775c771690b6854e05b3".into(), 210 | ], 211 | }, 212 | RpcBlockLevelParents { 213 | parent_hashes: vec![ 214 | "77241e302c6da8665c42341dda4adaea595ab1895f9652489dd2ceb49c247430".into(), 215 | "3cbb44c2b94303db662c9c66b8782905190f1e1635b63e34878d3f246fadfce3".into(), 216 | "44e74ef813090f8030bcd525ac10653ff182e00120f7e1f796fa0fc16ba7bb90".into(), 217 | "be2a33e87c3d60ab628471a420834383661801bb0bfd8e6c140071db1eb2f7a1".into(), 218 | "8194f1a045a94c078835c75dff2f3e836180baad9e955da840dc74c4dc2498f8".into(), 219 | "c201aec254a0e36476b2eeb124fdc6afc1b7d809c5e08b5e0e845aaf9b6c3957".into(), 220 | "e95ab4aa8e107cdb873f2dac527f16c4d5ac8760768a715e4669cb840c25317f".into(), 221 | "9a368774e506341afb46503e28e92e51bd7f7d4b53b9023d56f9b9ec991ac2a9".into(), 222 | "d9bc45ff64bb2bf14d4051a7604b28bad44d98bfe30e54ebc07fa45f62aabe39".into(), 223 | ], 224 | }, 225 | RpcBlockLevelParents { 226 | parent_hashes: vec![ 227 | "5cc98b2e3f6deb2990187058e4bfd2d1640653fc38a30b0f83231a965b413b0f".into(), 228 | "26927e0d032e830b732bdeb3094cb1a5fa6dec9f06375ea25fe57c2853ea0932".into(), 229 | "0ac8803976eacaa095c02f869fd7dc31072475940c3751d56283c49e2fefd41d".into(), 230 | "f676bdcb5855a0470efd2dab7a72cc5e5f39ff7eea0f433a9fe7b6a675bc2ac5".into(), 231 | "0cd218c009e21f910f9ddb09a0d059c4cd7d2ca65a2349df7a867dbedd81e9d4".into(), 232 | "891619c83c42895ce1b671cb7a4bcaed9130ab1dd4cc2d8147a1595056b55f92".into(), 233 | "a355db765adc8d3df88eb93d527f7f7ec869a75703ba86d4b36110e9a044593c".into(), 234 | "966815d153665387dc38e507e7458df3e6b0f04035ef9419883e03c08e2d753b".into(), 235 | "08c9090aabf175fdb63e8cf9a5f0783704c741c195157626401d949eaa6dbd04".into(), 236 | ], 237 | }, 238 | RpcBlockLevelParents { 239 | parent_hashes: vec![ 240 | "d7bf5e9c18cc79dda4e12efe564ecb8a4019e1c41f2d8217c0c3a43712ae226f".into(), 241 | "ce776631ae19b326a411a284741be01fb4f3aefc5def968eb6cceb8604864b4b".into(), 242 | "9ad373cbac10ea7e665b294a8a790691aa5246e6ff8fd0b7fb9b9a6a958ebf28".into(), 243 | ], 244 | }, 245 | RpcBlockLevelParents { 246 | parent_hashes: vec![ 247 | "ec5e8fc0bc0c637004cee262cef12e7cf6d9cd7772513dbd466176a07ab7c4f4".into(), 248 | "65fe09747779c31495e689b65f557b0a4af6535880b82553d126ff7213542905".into(), 249 | "5a64749599333e9655b43aa36728bb63bd286427441baa9f305d5c25e05229bb".into(), 250 | "332f7e8375b7c45e1ea0461d333c3c725f7467b441b7d0f5e80242b7a4a18eda".into(), 251 | ], 252 | }, 253 | RpcBlockLevelParents { 254 | parent_hashes: vec!["e80d7d9a0a4634f07bea5c5a00212fbc591bddfebb94334f4a2d928673d262ad".into()], 255 | }, 256 | RpcBlockLevelParents { 257 | parent_hashes: vec![ 258 | "abaa82988c683f4742c12099b732bd03639c1979752d837518243b74d6730124".into(), 259 | "5efe5661eaa0428917f55a58cc33db284d1f2caa05f1fd7b6602980f06d10723".into(), 260 | "0bf310b48cf62942017dd6680eb3ab13310eca1581afb3c5b619e5ce0682d0df".into(), 261 | "c1fade3928179a9dc28cd170b5b5544e7f9b63b83da374afa28e1478dc5c2997".into(), 262 | ], 263 | }, 264 | ], 265 | hash_merkle_root: "a98347ec1e71514eb26822162dc7c3992fd41f0b2ccc26e55e7bd8f3fa37215f".into(), 266 | accepted_id_merkle_root: "774b5216b5b872b6c2388dd950160e3ffa3bf0623c438655bb5c8c768ab33ae2".into(), 267 | utxo_commitment: "ee39218674008665e20a3acdf84abef35cabcc489158c0853fd5bfa954226139".into(), 268 | timestamp: -1426594953012613626, 269 | bits: 684408190, 270 | nonce: 8230160685758639177, 271 | daa_score: 15448880227546599629, 272 | blue_work: "ce5639b8ed46571e20eeaa7a62a078f8c55aef6edd6a35ed37a3d6cf98736abd".into(), 273 | pruning_point: "fc44c4f57cf8f7a2ba410a70d0ad49060355b9deb97012345603d9d0d1dcb0de".into(), 274 | blue_score: 29372123613087746, 275 | }; 276 | let expected_res = [ 277 | 245, 95, 9, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 98, 165, 238, 232, 42, 189, 244, 74, 45, 11, 117, 278 | 251, 24, 13, 175, 72, 167, 158, 224, 177, 13, 57, 70, 81, 133, 15, 212, 161, 120, 137, 46, 226, 133, 236, 279 | 225, 81, 20, 85, 120, 8, 117, 214, 78, 226, 211, 208, 208, 222, 107, 248, 249, 180, 76, 232, 95, 240, 68, 280 | 198, 177, 248, 59, 142, 136, 59, 191, 133, 122, 171, 153, 197, 178, 82, 199, 66, 156, 50, 243, 168, 174, 281 | 183, 158, 248, 86, 246, 89, 193, 143, 13, 206, 204, 119, 199, 94, 122, 129, 191, 222, 39, 95, 103, 207, 282 | 226, 66, 207, 60, 195, 84, 243, 237, 226, 214, 190, 204, 78, 163, 174, 94, 136, 82, 106, 159, 74, 87, 139, 283 | 203, 158, 242, 212, 166, 83, 20, 118, 141, 109, 41, 151, 97, 234, 158, 79, 90, 166, 174, 195, 252, 120, 284 | 198, 170, 224, 129, 172, 129, 32, 199, 32, 239, 205, 108, 234, 132, 182, 146, 94, 96, 123, 224, 99, 113, 285 | 111, 150, 221, 205, 208, 29, 117, 4, 92, 63, 0, 15, 138, 121, 107, 206, 108, 81, 44, 56, 1, 170, 202, 238, 286 | 7, 0, 0, 0, 0, 0, 0, 0, 223, 173, 91, 80, 236, 224, 184, 183, 193, 150, 93, 145, 129, 37, 27, 124, 156, 287 | 156, 165, 32, 90, 252, 22, 162, 54, 162, 239, 205, 210, 209, 45, 42, 121, 208, 116, 168, 40, 10, 233, 67, 288 | 158, 176, 214, 174, 202, 8, 35, 174, 2, 214, 125, 134, 106, 194, 196, 254, 74, 114, 80, 83, 218, 17, 155, 289 | 157, 79, 81, 81, 64, 162, 215, 35, 156, 64, 180, 90, 195, 149, 13, 148, 31, 196, 254, 28, 12, 185, 106, 290 | 211, 34, 214, 34, 130, 41, 95, 191, 225, 30, 38, 164, 51, 7, 109, 181, 193, 68, 76, 58, 52, 211, 42, 92, 291 | 74, 127, 251, 232, 209, 129, 247, 237, 59, 140, 254, 144, 79, 147, 248, 240, 109, 41, 188, 217, 237, 132, 292 | 123, 24, 46, 4, 100, 16, 244, 75, 196, 176, 243, 240, 58, 13, 6, 130, 10, 48, 242, 87, 248, 17, 65, 48, 293 | 103, 138, 192, 69, 134, 193, 227, 201, 52, 44, 139, 128, 85, 196, 102, 216, 134, 68, 29, 37, 153, 6, 214, 294 | 154, 205, 137, 75, 150, 138, 233, 240, 235, 157, 150, 92, 230, 164, 105, 60, 78, 190, 136, 21, 1, 183, 217, 295 | 132, 107, 102, 235, 2, 181, 126, 92, 218, 123, 108, 186, 104, 145, 214, 22, 189, 104, 108, 55, 184, 52, 9, 296 | 0, 0, 0, 0, 0, 0, 0, 97, 58, 200, 186, 82, 115, 74, 228, 227, 241, 33, 122, 205, 95, 131, 39, 8, 20, 48, 297 | 24, 103, 181, 208, 103, 17, 178, 56, 0, 28, 121, 87, 178, 119, 25, 206, 63, 49, 136, 223, 229, 125, 238, 298 | 191, 111, 130, 89, 90, 16, 247, 187, 86, 44, 160, 77, 92, 61, 39, 148, 41, 88, 198, 219, 50, 98, 103, 6, 299 | 73, 243, 188, 151, 217, 162, 49, 103, 53, 237, 230, 130, 165, 223, 230, 241, 160, 17, 251, 201, 138, 208, 300 | 251, 231, 144, 0, 60, 1, 232, 233, 150, 119, 3, 175, 102, 94, 159, 114, 64, 127, 75, 3, 212, 253, 180, 116, 301 | 170, 254, 138, 13, 62, 5, 21, 221, 70, 80, 207, 81, 23, 43, 129, 36, 139, 203, 127, 150, 158, 64, 11, 108, 302 | 91, 18, 119, 104, 177, 196, 18, 250, 233, 140, 245, 118, 49, 207, 55, 3, 59, 75, 74, 186, 125, 126, 211, 303 | 25, 186, 20, 114, 73, 201, 8, 172, 112, 209, 196, 6, 218, 222, 14, 130, 142, 182, 186, 13, 202, 168, 130, 304 | 133, 84, 62, 16, 33, 60, 100, 63, 200, 96, 59, 88, 96, 35, 102, 112, 186, 188, 173, 11, 215, 244, 196, 25, 305 | 14, 50, 54, 35, 168, 104, 209, 234, 225, 118, 159, 64, 162, 102, 49, 67, 27, 59, 213, 33, 86, 5, 210, 8, 306 | 111, 234, 212, 153, 172, 99, 164, 101, 61, 18, 40, 61, 86, 1, 156, 55, 149, 169, 138, 18, 109, 9, 207, 203, 307 | 227, 108, 220, 201, 55, 136, 165, 64, 159, 139, 110, 66, 194, 221, 131, 170, 70, 97, 24, 82, 173, 11, 80, 308 | 40, 119, 92, 119, 22, 144, 182, 133, 78, 5, 179, 9, 0, 0, 0, 0, 0, 0, 0, 119, 36, 30, 48, 44, 109, 168, 309 | 102, 92, 66, 52, 29, 218, 74, 218, 234, 89, 90, 177, 137, 95, 150, 82, 72, 157, 210, 206, 180, 156, 36, 310 | 116, 48, 60, 187, 68, 194, 185, 67, 3, 219, 102, 44, 156, 102, 184, 120, 41, 5, 25, 15, 30, 22, 53, 182, 311 | 62, 52, 135, 141, 63, 36, 111, 173, 252, 227, 68, 231, 78, 248, 19, 9, 15, 128, 48, 188, 213, 37, 172, 16, 312 | 101, 63, 241, 130, 224, 1, 32, 247, 225, 247, 150, 250, 15, 193, 107, 167, 187, 144, 190, 42, 51, 232, 124, 313 | 61, 96, 171, 98, 132, 113, 164, 32, 131, 67, 131, 102, 24, 1, 187, 11, 253, 142, 108, 20, 0, 113, 219, 30, 314 | 178, 247, 161, 129, 148, 241, 160, 69, 169, 76, 7, 136, 53, 199, 93, 255, 47, 62, 131, 97, 128, 186, 173, 315 | 158, 149, 93, 168, 64, 220, 116, 196, 220, 36, 152, 248, 194, 1, 174, 194, 84, 160, 227, 100, 118, 178, 316 | 238, 177, 36, 253, 198, 175, 193, 183, 216, 9, 197, 224, 139, 94, 14, 132, 90, 175, 155, 108, 57, 87, 233, 317 | 90, 180, 170, 142, 16, 124, 219, 135, 63, 45, 172, 82, 127, 22, 196, 213, 172, 135, 96, 118, 138, 113, 94, 318 | 70, 105, 203, 132, 12, 37, 49, 127, 154, 54, 135, 116, 229, 6, 52, 26, 251, 70, 80, 62, 40, 233, 46, 81, 319 | 189, 127, 125, 75, 83, 185, 2, 61, 86, 249, 185, 236, 153, 26, 194, 169, 217, 188, 69, 255, 100, 187, 43, 320 | 241, 77, 64, 81, 167, 96, 75, 40, 186, 212, 77, 152, 191, 227, 14, 84, 235, 192, 127, 164, 95, 98, 170, 321 | 190, 57, 9, 0, 0, 0, 0, 0, 0, 0, 92, 201, 139, 46, 63, 109, 235, 41, 144, 24, 112, 88, 228, 191, 210, 209, 322 | 100, 6, 83, 252, 56, 163, 11, 15, 131, 35, 26, 150, 91, 65, 59, 15, 38, 146, 126, 13, 3, 46, 131, 11, 115, 323 | 43, 222, 179, 9, 76, 177, 165, 250, 109, 236, 159, 6, 55, 94, 162, 95, 229, 124, 40, 83, 234, 9, 50, 10, 324 | 200, 128, 57, 118, 234, 202, 160, 149, 192, 47, 134, 159, 215, 220, 49, 7, 36, 117, 148, 12, 55, 81, 213, 325 | 98, 131, 196, 158, 47, 239, 212, 29, 246, 118, 189, 203, 88, 85, 160, 71, 14, 253, 45, 171, 122, 114, 204, 326 | 94, 95, 57, 255, 126, 234, 15, 67, 58, 159, 231, 182, 166, 117, 188, 42, 197, 12, 210, 24, 192, 9, 226, 31, 327 | 145, 15, 157, 219, 9, 160, 208, 89, 196, 205, 125, 44, 166, 90, 35, 73, 223, 122, 134, 125, 190, 221, 129, 328 | 233, 212, 137, 22, 25, 200, 60, 66, 137, 92, 225, 182, 113, 203, 122, 75, 202, 237, 145, 48, 171, 29, 212, 329 | 204, 45, 129, 71, 161, 89, 80, 86, 181, 95, 146, 163, 85, 219, 118, 90, 220, 141, 61, 248, 142, 185, 61, 330 | 82, 127, 127, 126, 200, 105, 167, 87, 3, 186, 134, 212, 179, 97, 16, 233, 160, 68, 89, 60, 150, 104, 21, 331 | 209, 83, 102, 83, 135, 220, 56, 229, 7, 231, 69, 141, 243, 230, 176, 240, 64, 53, 239, 148, 25, 136, 62, 3, 332 | 192, 142, 45, 117, 59, 8, 201, 9, 10, 171, 241, 117, 253, 182, 62, 140, 249, 165, 240, 120, 55, 4, 199, 65, 333 | 193, 149, 21, 118, 38, 64, 29, 148, 158, 170, 109, 189, 4, 3, 0, 0, 0, 0, 0, 0, 0, 215, 191, 94, 156, 24, 334 | 204, 121, 221, 164, 225, 46, 254, 86, 78, 203, 138, 64, 25, 225, 196, 31, 45, 130, 23, 192, 195, 164, 55, 335 | 18, 174, 34, 111, 206, 119, 102, 49, 174, 25, 179, 38, 164, 17, 162, 132, 116, 27, 224, 31, 180, 243, 174, 336 | 252, 93, 239, 150, 142, 182, 204, 235, 134, 4, 134, 75, 75, 154, 211, 115, 203, 172, 16, 234, 126, 102, 91, 337 | 41, 74, 138, 121, 6, 145, 170, 82, 70, 230, 255, 143, 208, 183, 251, 155, 154, 106, 149, 142, 191, 40, 4, 338 | 0, 0, 0, 0, 0, 0, 0, 236, 94, 143, 192, 188, 12, 99, 112, 4, 206, 226, 98, 206, 241, 46, 124, 246, 217, 339 | 205, 119, 114, 81, 61, 189, 70, 97, 118, 160, 122, 183, 196, 244, 101, 254, 9, 116, 119, 121, 195, 20, 149, 340 | 230, 137, 182, 95, 85, 123, 10, 74, 246, 83, 88, 128, 184, 37, 83, 209, 38, 255, 114, 19, 84, 41, 5, 90, 341 | 100, 116, 149, 153, 51, 62, 150, 85, 180, 58, 163, 103, 40, 187, 99, 189, 40, 100, 39, 68, 27, 170, 159, 342 | 48, 93, 92, 37, 224, 82, 41, 187, 51, 47, 126, 131, 117, 183, 196, 94, 30, 160, 70, 29, 51, 60, 60, 114, 343 | 95, 116, 103, 180, 65, 183, 208, 245, 232, 2, 66, 183, 164, 161, 142, 218, 1, 0, 0, 0, 0, 0, 0, 0, 232, 13, 344 | 125, 154, 10, 70, 52, 240, 123, 234, 92, 90, 0, 33, 47, 188, 89, 27, 221, 254, 187, 148, 51, 79, 74, 45, 345 | 146, 134, 115, 210, 98, 173, 4, 0, 0, 0, 0, 0, 0, 0, 171, 170, 130, 152, 140, 104, 63, 71, 66, 193, 32, 346 | 153, 183, 50, 189, 3, 99, 156, 25, 121, 117, 45, 131, 117, 24, 36, 59, 116, 214, 115, 1, 36, 94, 254, 86, 347 | 97, 234, 160, 66, 137, 23, 245, 90, 88, 204, 51, 219, 40, 77, 31, 44, 170, 5, 241, 253, 123, 102, 2, 152, 348 | 15, 6, 209, 7, 35, 11, 243, 16, 180, 140, 246, 41, 66, 1, 125, 214, 104, 14, 179, 171, 19, 49, 14, 202, 21, 349 | 129, 175, 179, 197, 182, 25, 229, 206, 6, 130, 208, 223, 193, 250, 222, 57, 40, 23, 154, 157, 194, 140, 350 | 209, 112, 181, 181, 84, 78, 127, 155, 99, 184, 61, 163, 116, 175, 162, 142, 20, 120, 220, 92, 41, 151, 169, 351 | 131, 71, 236, 30, 113, 81, 78, 178, 104, 34, 22, 45, 199, 195, 153, 47, 212, 31, 11, 44, 204, 38, 229, 94, 352 | 123, 216, 243, 250, 55, 33, 95, 119, 75, 82, 22, 181, 184, 114, 182, 194, 56, 141, 217, 80, 22, 14, 63, 353 | 250, 59, 240, 98, 60, 67, 134, 85, 187, 92, 140, 118, 138, 179, 58, 226, 238, 57, 33, 134, 116, 0, 134, 354 | 101, 226, 10, 58, 205, 248, 74, 190, 243, 92, 171, 204, 72, 145, 88, 192, 133, 63, 213, 191, 169, 84, 34, 355 | 97, 57, 0, 0, 0, 0, 0, 0, 0, 0, 126, 61, 203, 40, 0, 0, 0, 0, 0, 0, 0, 0, 205, 144, 120, 28, 183, 114, 101, 356 | 214, 2, 200, 65, 114, 202, 89, 104, 0, 32, 0, 0, 0, 0, 0, 0, 0, 206, 86, 57, 184, 237, 70, 87, 30, 32, 238, 357 | 170, 122, 98, 160, 120, 248, 197, 90, 239, 110, 221, 106, 53, 237, 55, 163, 214, 207, 152, 115, 106, 189, 358 | 252, 68, 196, 245, 124, 248, 247, 162, 186, 65, 10, 112, 208, 173, 73, 6, 3, 85, 185, 222, 185, 112, 18, 359 | 52, 86, 3, 217, 208, 209, 220, 176, 222, 360 | ]; 361 | let mut buf = Buf(Vec::with_capacity(1951)); 362 | serialize_header(&mut buf, &header, true); 363 | assert_eq!(&expected_res[..], &buf.0); 364 | 365 | let expected_hash = Hash::from_le_bytes([ 366 | 85, 146, 211, 217, 138, 239, 47, 85, 152, 59, 58, 16, 4, 149, 129, 179, 172, 226, 174, 233, 160, 96, 202, 367 | 54, 6, 225, 64, 142, 106, 0, 110, 137, 368 | ]); 369 | let mut hasher = HeaderHasher::new(); 370 | hasher.write(buf.0); 371 | assert_eq!(hasher.finalize(), expected_hash); 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /src/pow/hasher.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::unreadable_literal)] 2 | use crate::Hash; 3 | use blake2b_simd::State as Blake2bState; 4 | 5 | const BLOCK_HASH_DOMAIN: &[u8] = b"BlockHash"; 6 | 7 | #[derive(Clone, Copy)] 8 | pub(super) struct PowHasher([u64; 25]); 9 | 10 | #[derive(Clone, Copy)] 11 | pub(super) struct HeavyHasher; 12 | 13 | #[derive(Clone)] 14 | pub struct HeaderHasher(Blake2bState); 15 | 16 | impl PowHasher { 17 | // The initial state of `cSHAKE256("ProofOfWorkHash")` 18 | // [10] -> 1123092876221303310 ^ 0x04(padding byte) = 1123092876221303306 19 | // [16] -> 10306167911662716186 ^ 0x8000000000000000(final padding) = 1082795874807940378 20 | #[rustfmt::skip] 21 | const INITIAL_STATE: [u64; 25] = [ 22 | 1242148031264380989, 3008272977830772284, 2188519011337848018, 1992179434288343456, 8876506674959887717, 23 | 5399642050693751366, 1745875063082670864, 8605242046444978844, 17936695144567157056, 3343109343542796272, 24 | 1123092876221303306, 4963925045340115282, 17037383077651887893, 16629644495023626889, 12833675776649114147, 25 | 3784524041015224902, 1082795874807940378, 13952716920571277634, 13411128033953605860, 15060696040649351053, 26 | 9928834659948351306, 5237849264682708699, 12825353012139217522, 6706187291358897596, 196324915476054915, 27 | ]; 28 | #[inline(always)] 29 | pub(super) fn new(pre_pow_hash: Hash, timestamp: u64) -> Self { 30 | let mut start = Self::INITIAL_STATE; 31 | for (&pre_pow_word, state_word) in pre_pow_hash.0.iter().zip(start.iter_mut()) { 32 | *state_word ^= pre_pow_word; 33 | } 34 | start[4] ^= timestamp; 35 | Self(start) 36 | } 37 | 38 | #[inline(always)] 39 | pub(super) fn finalize_with_nonce(mut self, nonce: u64) -> Hash { 40 | self.0[9] ^= nonce; 41 | super::keccak::f1600(&mut self.0); 42 | Hash::new(self.0[..4].try_into().unwrap()) 43 | } 44 | } 45 | 46 | impl HeavyHasher { 47 | // The initial state of `cSHAKE256("HeavyHash")` 48 | // [4] -> 16654558671554924254 ^ 0x04(padding byte) = 16654558671554924250 49 | // [16] -> 9793466274154320918 ^ 0x8000000000000000(final padding) = 570094237299545110 50 | #[rustfmt::skip] 51 | const INITIAL_STATE: [u64; 25] = [ 52 | 4239941492252378377, 8746723911537738262, 8796936657246353646, 1272090201925444760, 16654558671554924250, 53 | 8270816933120786537, 13907396207649043898, 6782861118970774626, 9239690602118867528, 11582319943599406348, 54 | 17596056728278508070, 15212962468105129023, 7812475424661425213, 3370482334374859748, 5690099369266491460, 55 | 8596393687355028144, 570094237299545110, 9119540418498120711, 16901969272480492857, 13372017233735502424, 56 | 14372891883993151831, 5171152063242093102, 10573107899694386186, 6096431547456407061, 1592359455985097269, 57 | ]; 58 | #[inline(always)] 59 | pub(super) fn hash(in_hash: Hash) -> Hash { 60 | let mut state = Self::INITIAL_STATE; 61 | for (&pre_pow_word, state_word) in in_hash.0.iter().zip(state.iter_mut()) { 62 | *state_word ^= pre_pow_word; 63 | } 64 | super::keccak::f1600(&mut state); 65 | Hash::new(state[..4].try_into().unwrap()) 66 | } 67 | } 68 | 69 | impl HeaderHasher { 70 | #[inline(always)] 71 | pub fn new() -> Self { 72 | Self(blake2b_simd::Params::new().hash_length(32).key(BLOCK_HASH_DOMAIN).to_state()) 73 | } 74 | 75 | pub fn write>(&mut self, data: A) { 76 | self.0.update(data.as_ref()); 77 | } 78 | 79 | #[inline(always)] 80 | pub fn finalize(self) -> Hash { 81 | Hash::from_le_bytes(self.0.finalize().as_bytes().try_into().expect("this is 32 bytes")) 82 | } 83 | } 84 | 85 | pub trait Hasher { 86 | fn update>(&mut self, data: A) -> &mut Self; 87 | } 88 | 89 | impl Hasher for HeaderHasher { 90 | fn update>(&mut self, data: A) -> &mut Self { 91 | self.write(data); 92 | self 93 | } 94 | } 95 | 96 | #[cfg(test)] 97 | mod tests { 98 | use crate::pow::hasher::{HeavyHasher, PowHasher}; 99 | use crate::Hash; 100 | use sha3::digest::{ExtendableOutput, Update, XofReader}; 101 | use sha3::{CShake256, CShake256Core}; 102 | 103 | const PROOF_OF_WORK_DOMAIN: &[u8] = b"ProofOfWorkHash"; 104 | const HEAVY_HASH_DOMAIN: &[u8] = b"HeavyHash"; 105 | 106 | #[test] 107 | fn test_pow_hash() { 108 | let timestamp: u64 = 5435345234; 109 | let nonce: u64 = 432432432; 110 | let pre_pow_hash = Hash::from_le_bytes([42; 32]); 111 | let hasher = PowHasher::new(pre_pow_hash, timestamp); 112 | let hash1 = hasher.finalize_with_nonce(nonce); 113 | 114 | let hasher = CShake256::from_core(CShake256Core::new(PROOF_OF_WORK_DOMAIN)) 115 | .chain(pre_pow_hash.to_le_bytes()) 116 | .chain(timestamp.to_le_bytes()) 117 | .chain([0u8; 32]) 118 | .chain(nonce.to_le_bytes()); 119 | let mut hash2 = [0u8; 32]; 120 | hasher.finalize_xof().read(&mut hash2); 121 | assert_eq!(Hash::from_le_bytes(hash2), hash1); 122 | } 123 | 124 | #[test] 125 | fn test_heavy_hash() { 126 | let val = Hash::from_le_bytes([42; 32]); 127 | let hash1 = HeavyHasher::hash(val); 128 | 129 | let hasher = CShake256::from_core(CShake256Core::new(HEAVY_HASH_DOMAIN)).chain(val.to_le_bytes()); 130 | let mut hash2 = [0u8; 32]; 131 | hasher.finalize_xof().read(&mut hash2); 132 | assert_eq!(Hash::from_le_bytes(hash2), hash1); 133 | } 134 | } 135 | 136 | #[cfg(all(test, feature = "bench"))] 137 | mod benches { 138 | extern crate test; 139 | 140 | use self::test::{black_box, Bencher}; 141 | use super::{HeavyHasher, PowHasher}; 142 | use crate::Hash; 143 | 144 | #[bench] 145 | pub fn bench_pow_hash(bh: &mut Bencher) { 146 | let timestamp: u64 = 5435345234; 147 | let mut nonce: u64 = 432432432; 148 | let pre_pow_hash = Hash::from_le_bytes([42; 32]); 149 | let mut hasher = PowHasher::new(pre_pow_hash, timestamp); 150 | 151 | bh.iter(|| { 152 | for _ in 0..100 { 153 | black_box(&mut hasher); 154 | black_box(&mut nonce); 155 | black_box(hasher.finalize_with_nonce(nonce)); 156 | } 157 | }); 158 | } 159 | 160 | #[bench] 161 | pub fn bench_heavy_hash(bh: &mut Bencher) { 162 | let mut data = Hash::from_le_bytes([42; 32]); 163 | bh.iter(|| { 164 | for _ in 0..100 { 165 | black_box(&mut data); 166 | black_box(HeavyHasher::hash(data)); 167 | } 168 | }); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/pow/keccak.rs: -------------------------------------------------------------------------------- 1 | #[cfg(any(not(target_arch = "x86_64"), feature = "no-asm"))] 2 | pub(super) fn f1600(state: &mut [u64; 25]) { 3 | keccak::f1600(state); 4 | } 5 | 6 | #[cfg(all(target_arch = "x86_64", not(feature = "no-asm")))] 7 | pub(super) fn f1600(state: &mut [u64; 25]) { 8 | extern "C" { 9 | fn KeccakF1600(state: &mut [u64; 25]); 10 | } 11 | unsafe { KeccakF1600(state) } 12 | } 13 | -------------------------------------------------------------------------------- /src/pow/xoshiro.rs: -------------------------------------------------------------------------------- 1 | use crate::Hash; 2 | use std::num::Wrapping; 3 | 4 | pub(super) struct XoShiRo256PlusPlus { 5 | s0: Wrapping, 6 | s1: Wrapping, 7 | s2: Wrapping, 8 | s3: Wrapping, 9 | } 10 | 11 | impl XoShiRo256PlusPlus { 12 | #[inline] 13 | pub(super) fn new(hash: Hash) -> Self { 14 | Self { s0: Wrapping(hash.0[0]), s1: Wrapping(hash.0[1]), s2: Wrapping(hash.0[2]), s3: Wrapping(hash.0[3]) } 15 | } 16 | 17 | #[inline] 18 | pub(super) fn u64(&mut self) -> u64 { 19 | let res = self.s0 + Wrapping((self.s0 + self.s3).0.rotate_left(23)); 20 | let t = self.s1 << 17; 21 | self.s2 ^= self.s0; 22 | self.s3 ^= self.s1; 23 | self.s1 ^= self.s2; 24 | self.s0 ^= self.s3; 25 | 26 | self.s2 ^= t; 27 | self.s3 = Wrapping(self.s3.0.rotate_left(45)); 28 | 29 | res.0 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/spectred_messages.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | pow::{self, HeaderHasher}, 3 | proto::{ 4 | spectred_message::Payload, GetBlockTemplateRequestMessage, GetInfoRequestMessage, 5 | NotifyBlockAddedRequestMessage, NotifyNewBlockTemplateRequestMessage, RpcBlock, SpectredMessage, 6 | SubmitBlockRequestMessage, 7 | }, 8 | Hash, 9 | }; 10 | 11 | impl SpectredMessage { 12 | #[must_use] 13 | #[inline(always)] 14 | pub fn get_info_request() -> Self { 15 | SpectredMessage { payload: Some(Payload::GetInfoRequest(GetInfoRequestMessage {})) } 16 | } 17 | #[must_use] 18 | #[inline(always)] 19 | pub fn notify_block_added() -> Self { 20 | SpectredMessage { payload: Some(Payload::NotifyBlockAddedRequest(NotifyBlockAddedRequestMessage {})) } 21 | } 22 | #[must_use] 23 | #[inline(always)] 24 | pub fn submit_block(block: RpcBlock) -> Self { 25 | SpectredMessage { 26 | payload: Some(Payload::SubmitBlockRequest(SubmitBlockRequestMessage { 27 | block: Some(block), 28 | allow_non_daa_blocks: false, 29 | })), 30 | } 31 | } 32 | } 33 | 34 | impl From for SpectredMessage { 35 | #[inline(always)] 36 | fn from(a: GetInfoRequestMessage) -> Self { 37 | SpectredMessage { payload: Some(Payload::GetInfoRequest(a)) } 38 | } 39 | } 40 | impl From for SpectredMessage { 41 | #[inline(always)] 42 | fn from(a: NotifyBlockAddedRequestMessage) -> Self { 43 | SpectredMessage { payload: Some(Payload::NotifyBlockAddedRequest(a)) } 44 | } 45 | } 46 | 47 | impl From for SpectredMessage { 48 | #[inline(always)] 49 | fn from(a: GetBlockTemplateRequestMessage) -> Self { 50 | SpectredMessage { payload: Some(Payload::GetBlockTemplateRequest(a)) } 51 | } 52 | } 53 | 54 | impl From for SpectredMessage { 55 | fn from(a: NotifyNewBlockTemplateRequestMessage) -> Self { 56 | SpectredMessage { payload: Some(Payload::NotifyNewBlockTemplateRequest(a)) } 57 | } 58 | } 59 | 60 | impl RpcBlock { 61 | #[must_use] 62 | #[inline(always)] 63 | pub fn block_hash(&self) -> Option { 64 | let mut hasher = HeaderHasher::new(); 65 | pow::serialize_header(&mut hasher, self.header.as_ref()?, false); 66 | Some(hasher.finalize()) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/swap_rust.rs: -------------------------------------------------------------------------------- 1 | use arc_swap::{ArcSwapOption, Guard, RefCnt}; 2 | use std::ops::Deref; 3 | use sync::{Arc, Condvar, Mutex}; 4 | 5 | pub struct Shared { 6 | inner: ArcSwapOption, 7 | wait_cv: Condvar, 8 | wait_mutex: Mutex<()>, 9 | } 10 | 11 | pub struct WatchSwap { 12 | shared: Arc>, 13 | cached: Option>, 14 | } 15 | 16 | impl Clone for WatchSwap { 17 | fn clone(&self) -> Self { 18 | Self { shared: Arc::clone(&self.shared), cached: self.cached.clone() } 19 | } 20 | } 21 | 22 | impl WatchSwap { 23 | #[allow(dead_code)] 24 | pub fn init(val: impl Into>) -> Self { 25 | let val = val.into().map(Arc::new); 26 | Self { 27 | shared: Arc::new(Shared { 28 | inner: ArcSwapOption::new(val.clone()), 29 | wait_cv: Condvar::new(), 30 | wait_mutex: Mutex::new(()), 31 | }), 32 | cached: val, 33 | } 34 | } 35 | pub fn empty() -> Self { 36 | Self { 37 | shared: Arc::new(Shared { 38 | inner: ArcSwapOption::const_empty(), 39 | wait_cv: Condvar::new(), 40 | wait_mutex: Mutex::new(()), 41 | }), 42 | cached: None, 43 | } 44 | } 45 | 46 | fn wake_up_threads(&self) { 47 | // Make sure no receiver is "almost" waiting (holding the lock but hasn't entered the Condvar yet) 48 | let _lock = self.shared.wait_mutex.lock(); 49 | self.shared.wait_cv.notify_all(); 50 | } 51 | 52 | #[inline] 53 | fn get_changed_inner<'a>(cached: &'a mut Option>, inner: &'a ArcSwapOption) -> bool { 54 | // TODO: Optimize using `arc_swap::Cache` when https://github.com/vorner/arc-swap/pull/91 is merged. 55 | let cur_ptr = RefCnt::as_ptr(&*cached); 56 | let cheap_load = inner.load(); 57 | if cur_ptr != RefCnt::as_ptr(&*cheap_load) { 58 | *cached = Guard::into_inner(cheap_load); 59 | true 60 | } else { 61 | false 62 | } 63 | } 64 | 65 | #[inline] 66 | pub fn get_changed(&mut self) -> Option>> + '_> { 67 | Self::get_changed_inner(&mut self.cached, &self.shared.inner).then_some(&self.cached) 68 | } 69 | 70 | #[allow(dead_code)] 71 | pub fn peek_cached(&self) -> impl Deref>> + '_ { 72 | &self.cached 73 | } 74 | 75 | pub fn swap(&self, val: impl Into>) -> Option> { 76 | let old = self.shared.inner.swap(val.into().map(Arc::new)); 77 | self.wake_up_threads(); 78 | old 79 | } 80 | 81 | pub fn wait_for_change(&mut self) -> impl Deref>> + '_ { 82 | let mut guard = self.shared.wait_mutex.lock(); 83 | loop { 84 | if Self::get_changed_inner(&mut self.cached, &self.shared.inner) { 85 | return &self.cached; 86 | } 87 | guard = self.shared.wait_cv.wait(guard); 88 | } 89 | } 90 | } 91 | 92 | mod sync { 93 | #[cfg(all(feature = "parking_lot", feature = "shuttle"))] 94 | compile_error!("Can't use sync primitives both from parking_lot and from shuttle"); 95 | 96 | #[cfg(feature = "parking_lot")] 97 | use parking::{Condvar as CondvarInternal, Mutex as MutexInternal, MutexGuard}; 98 | 99 | #[cfg(feature = "shuttle")] 100 | use shuttle::sync::{Condvar as CondvarInternal, Mutex as MutexInternal, MutexGuard}; 101 | #[cfg(not(any(feature = "shuttle", feature = "parking_lot")))] 102 | use std::sync::{Condvar as CondvarInternal, Mutex as MutexInternal, MutexGuard}; 103 | 104 | #[cfg(feature = "shuttle")] 105 | pub use shuttle::sync::Arc; 106 | #[cfg(all(feature = "shuttle", test))] 107 | pub use shuttle::{sync::Barrier, thread}; 108 | 109 | #[cfg(not(feature = "shuttle"))] 110 | pub use std::sync::Arc; 111 | 112 | #[cfg(all(not(feature = "shuttle"), test))] 113 | pub use std::{sync::Barrier, thread}; 114 | 115 | pub struct Mutex(MutexInternal); 116 | impl Mutex { 117 | pub fn new(val: T) -> Self { 118 | Self(MutexInternal::new(val)) 119 | } 120 | 121 | #[inline(always)] 122 | pub fn lock(&self) -> MutexGuard { 123 | #[cfg(not(feature = "parking_lot"))] 124 | return self.0.lock().unwrap_or_else(|e| e.into_inner()); 125 | #[cfg(feature = "parking_lot")] 126 | return self.0.lock(); 127 | } 128 | } 129 | 130 | pub struct Condvar(CondvarInternal); 131 | 132 | impl Condvar { 133 | pub fn new() -> Self { 134 | Self(CondvarInternal::new()) 135 | } 136 | 137 | #[allow(unused_mut)] 138 | #[inline(always)] 139 | pub fn wait<'a, T>(&self, mut guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> { 140 | #[cfg(not(feature = "parking_lot"))] 141 | return self.0.wait(guard).unwrap_or_else(|e| e.into_inner()); 142 | #[cfg(feature = "parking_lot")] 143 | { 144 | self.0.wait(&mut guard); 145 | guard 146 | } 147 | } 148 | 149 | #[inline(always)] 150 | pub fn notify_all(&self) { 151 | self.0.notify_all(); 152 | } 153 | } 154 | } 155 | 156 | #[cfg(test)] 157 | mod tests { 158 | use crate::swap_rust::{ 159 | sync::{thread, Arc, Barrier}, 160 | WatchSwap, 161 | }; 162 | 163 | fn channel(val: T) -> (WatchSwap, WatchSwap) { 164 | let a = WatchSwap::empty(); 165 | let b = a.clone(); 166 | b.clone().swap(val); 167 | (a, b) 168 | } 169 | 170 | #[test] 171 | fn test_sending_val() { 172 | multi_test_runner( 173 | || { 174 | let (rx, mut tx) = channel("One"); 175 | let mut tx2 = tx.clone(); 176 | assert_eq!(tx.get_changed().as_deref().map(|a| a.as_deref()), Some(Some(&"One"))); 177 | assert_eq!(tx.get_changed().as_deref().map(|a| a.as_deref()), None); 178 | let mut tx3 = tx.clone(); 179 | assert_eq!(tx3.get_changed().as_deref().map(|a| a.as_deref()), None); 180 | assert_eq!(tx2.get_changed().as_deref().map(|a| a.as_deref()), Some(Some(&"One"))); 181 | rx.swap("Two"); 182 | assert_eq!(tx.get_changed().as_deref().map(|a| a.as_deref()), Some(Some(&"Two"))); 183 | assert_eq!(tx2.get_changed().as_deref().map(|a| a.as_deref()), Some(Some(&"Two"))); 184 | assert_eq!(tx3.get_changed().as_deref().map(|a| a.as_deref()), Some(Some(&"Two"))); 185 | }, 186 | false, 187 | ) 188 | } 189 | 190 | #[test] 191 | fn test_sending_val_waiting() { 192 | multi_test_runner( 193 | || { 194 | let (rx, mut tx) = channel("One"); 195 | let mut tx2 = tx.clone(); 196 | assert_eq!(tx.wait_for_change().as_deref().copied(), Some("One")); 197 | assert_eq!(tx.get_changed().as_deref().map(|a| a.as_deref()), None); 198 | let mut tx3 = tx.clone(); 199 | assert_eq!(tx3.get_changed().as_deref().map(|a| a.as_deref()), None); 200 | assert_eq!(tx2.wait_for_change().as_deref().copied(), Some("One")); 201 | rx.swap("Two").unwrap(); 202 | assert_eq!(tx.wait_for_change().as_deref().copied(), Some("Two")); 203 | assert_eq!(tx2.wait_for_change().as_deref().copied(), Some("Two")); 204 | assert_eq!(tx3.wait_for_change().as_deref().copied(), Some("Two")); 205 | }, 206 | false, 207 | ) 208 | } 209 | 210 | fn multi_test_runner(f: impl Fn() + Sync + Send + 'static, parallel: bool) { 211 | let mut iters = if parallel { 10_000 } else { 5 }; 212 | if !cfg!(debug_assertions) { 213 | iters *= 10; 214 | } 215 | if cfg!(feature = "parking_lot") || cfg!(feature = "shuttle") { 216 | iters *= 10; 217 | } 218 | #[cfg(feature = "shuttle")] 219 | shuttle::check_random(f, iters); 220 | #[cfg(not(feature = "shuttle"))] 221 | for _ in 0..iters { 222 | f(); 223 | } 224 | } 225 | 226 | #[test] 227 | fn test_waiting_on_val() { 228 | multi_test_runner( 229 | || { 230 | let (rx, mut tx) = channel("One"); 231 | assert_eq!(tx.get_changed().as_deref().map(|a| a.as_deref()), Some(Some(&"One"))); 232 | let mut tx2 = tx.clone(); 233 | assert_eq!(tx.get_changed().as_deref().map(|a| a.as_deref()), None); 234 | assert_eq!(tx2.get_changed().as_deref().map(|a| a.as_deref()), None); 235 | let barrier = Arc::new(Barrier::new(3)); 236 | let barrier_clone = Arc::clone(&barrier); 237 | let handle1 = thread::spawn(move || { 238 | barrier_clone.wait(); 239 | assert_eq!(tx.wait_for_change().as_deref().copied(), Some("Two")); 240 | }); 241 | let barrier_clone = Arc::clone(&barrier); 242 | let handle2 = thread::spawn(move || { 243 | barrier_clone.wait(); 244 | assert_eq!(tx2.wait_for_change().as_deref().copied(), Some("Two")); 245 | }); 246 | barrier.wait(); 247 | rx.swap("Two"); 248 | 249 | handle1.join().unwrap(); 250 | handle2.join().unwrap(); 251 | }, 252 | true, 253 | ) 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/target.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use std::fmt; 3 | 4 | pub fn u256_from_compact_target(bits: u32) -> Uint256 { 5 | // This is a floating-point "compact" encoding originally used by 6 | // OpenSSL, which satoshi put into consensus code, so we're stuck 7 | // with it. The exponent needs to have 3 subtracted from it, hence 8 | // this goofy decoding code: 9 | let (mant, expt) = { 10 | let unshifted_expt = bits >> 24; 11 | if unshifted_expt <= 3 { 12 | ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0) 13 | } else { 14 | (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3)) 15 | } 16 | }; 17 | 18 | // The mantissa is signed but may not be negative 19 | if mant > 0x7FFFFF { 20 | Default::default() 21 | } else { 22 | Uint256::from_u64(mant as u64) << (expt as usize) 23 | } 24 | } 25 | 26 | /// Little-endian large integer type 27 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)] 28 | pub struct Uint256(pub [u64; 4]); 29 | 30 | impl Uint256 { 31 | #[inline(always)] 32 | pub fn new(v: [u64; 4]) -> Self { 33 | Self(v) 34 | } 35 | /// Create an object from a given unsigned 64-bit integer 36 | #[inline] 37 | pub fn from_u64(init: u64) -> Uint256 { 38 | let mut ret = [0; 4]; 39 | ret[0] = init; 40 | Uint256(ret) 41 | } 42 | 43 | /// Creates big integer value from a byte slice using 44 | /// little-endian encoding 45 | #[inline(always)] 46 | pub fn from_le_bytes(bytes: [u8; 32]) -> Uint256 { 47 | let mut out = [0u64; 4]; 48 | // This should optimize to basically a transmute. 49 | out.iter_mut() 50 | .zip(bytes.chunks_exact(8)) 51 | .for_each(|(word, bytes)| *word = u64::from_le_bytes(bytes.try_into().unwrap())); 52 | Self(out) 53 | } 54 | 55 | #[inline(always)] 56 | pub fn to_le_bytes(self) -> [u8; 32] { 57 | let mut out = [0u8; 32]; 58 | // This should optimize to basically a transmute. 59 | out.chunks_exact_mut(8).zip(self.0).for_each(|(bytes, word)| bytes.copy_from_slice(&word.to_le_bytes())); 60 | out 61 | } 62 | } 63 | 64 | impl fmt::LowerHex for Uint256 { 65 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 66 | self.to_le_bytes().iter().try_for_each(|&c| write!(f, "{:02x}", c)) 67 | } 68 | } 69 | 70 | impl PartialOrd for Uint256 { 71 | #[inline(always)] 72 | fn partial_cmp(&self, other: &Uint256) -> Option { 73 | Some(self.cmp(other)) 74 | } 75 | } 76 | 77 | impl Ord for Uint256 { 78 | #[inline(always)] 79 | fn cmp(&self, other: &Uint256) -> Ordering { 80 | // We need to manually implement ordering because we use little-endian 81 | // and the auto derive is a lexicographic ordering(i.e. memcmp) 82 | // which with numbers is equivalent to big-endian 83 | Iterator::cmp(self.0.iter().rev(), other.0.iter().rev()) 84 | } 85 | } 86 | 87 | impl core::ops::Shl for Uint256 { 88 | type Output = Uint256; 89 | 90 | fn shl(self, shift: usize) -> Uint256 { 91 | let Uint256(ref original) = self; 92 | let mut ret = [0u64; 4]; 93 | let word_shift = shift / 64; 94 | let bit_shift = shift % 64; 95 | for i in 0..4 { 96 | // Shift 97 | if bit_shift < 64 && i + word_shift < 4 { 98 | ret[i + word_shift] += original[i] << bit_shift; 99 | } 100 | // Carry 101 | if bit_shift > 0 && i + word_shift + 1 < 4 { 102 | ret[i + word_shift + 1] += original[i] >> (64 - bit_shift); 103 | } 104 | } 105 | Uint256(ret) 106 | } 107 | } 108 | --------------------------------------------------------------------------------