mirror of
https://github.com/BLAKE3-team/BLAKE3
synced 2024-05-27 21:06:05 +02:00
Merge branch 'master' into master
This commit is contained in:
commit
37f7b54994
|
@ -9,8 +9,9 @@ import sys
|
|||
ROOT = Path(__file__).parent.parent.parent
|
||||
RUST_TARGET = sys.argv[1]
|
||||
|
||||
subprocess.run(["cargo", "build", "--target", sys.argv[1], "--release"],
|
||||
cwd=ROOT / "b3sum")
|
||||
subprocess.run(
|
||||
["cargo", "build", "--target", sys.argv[1], "--release"], cwd=ROOT / "b3sum"
|
||||
)
|
||||
|
||||
if platform.system() == "Windows":
|
||||
original_exe_name = "b3sum.exe"
|
||||
|
|
|
@ -25,10 +25,20 @@ jobs:
|
|||
{ "os": "windows-latest", "toolchain": "x86_64-pc-windows-msvc", "name": "Windows MSVC" },
|
||||
{ "os": "windows-latest", "toolchain": "x86_64-pc-windows-gnu", "name": "Windows GNU" }
|
||||
]
|
||||
channel: [stable, beta, nightly]
|
||||
channel: [
|
||||
"stable",
|
||||
"beta",
|
||||
"nightly",
|
||||
# The current MSRV. This crate doesn't have an official MSRV policy,
|
||||
# but in practice we'll probably do what libc does:
|
||||
# https://github.com/rust-lang/libs-team/issues/72.
|
||||
# This test target is here so that we notice if we accidentally bump
|
||||
# the MSRV, but it's not a promise that we won't bump it.
|
||||
"1.60.0",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ format('{0}-{1}', matrix.channel, matrix.target.toolchain) }}
|
||||
|
@ -140,7 +150,7 @@ jobs:
|
|||
- mips-unknown-linux-gnu
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
@ -170,7 +180,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
# Test the intrinsics-based implementations.
|
||||
- run: make -f Makefile.testing test
|
||||
working-directory: ./c
|
||||
|
@ -222,7 +232,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
@ -234,6 +244,38 @@ jobs:
|
|||
run: cargo build --target aarch64-apple-darwin
|
||||
working-directory: ./b3sum
|
||||
|
||||
build_tinycc:
|
||||
name: build with the Tiny C Compiler
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: install TCC
|
||||
run: sudo apt-get install -y tcc
|
||||
- name: compile
|
||||
run: >
|
||||
tcc -shared -O3 -o libblake3.so \
|
||||
-DBLAKE3_NO_SSE2 -DBLAKE3_NO_SSE41 -DBLAKE3_NO_AVX2 -DBLAKE3_NO_AVX512 \
|
||||
blake3.c blake3_dispatch.c blake3_portable.c
|
||||
working-directory: ./c
|
||||
|
||||
# See https://github.com/BLAKE3-team/BLAKE3/issues/271 for why we test this.
|
||||
# Note that this isn't guaranteed to execute on an AVX-512-supporting server,
|
||||
# but hopefully at least some of the time it will.
|
||||
gcc54:
|
||||
name: "compile and test with GCC 5.4"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: gcc:5.4
|
||||
options: -v ${{ github.workspace }}:/work
|
||||
run: |
|
||||
cat /proc/cpuinfo
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal
|
||||
cd /work
|
||||
~/.cargo/bin/cargo test --features prefer_intrinsics
|
||||
|
||||
# CMake build test (Library only), current macOS/Linux only.
|
||||
cmake_build:
|
||||
name: CMake ${{ matrix.os }}
|
||||
|
|
|
@ -23,8 +23,8 @@ jobs:
|
|||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-python@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: pip install PyGithub
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import github
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
RETRIES = 10
|
||||
|
||||
|
@ -10,7 +11,7 @@ g = github.Github(os.environ["GITHUB_TOKEN"])
|
|||
tag_name = os.environ["GITHUB_TAG"]
|
||||
tag_prefix = "refs/tags/"
|
||||
if tag_name.startswith(tag_prefix):
|
||||
tag_name = tag_name[len(tag_prefix):]
|
||||
tag_name = tag_name[len(tag_prefix) :]
|
||||
assert len(sys.argv) == 2
|
||||
asset_path = sys.argv[1]
|
||||
asset_name = os.path.basename(asset_path)
|
||||
|
@ -34,13 +35,20 @@ except github.GithubException as github_error:
|
|||
else:
|
||||
raise
|
||||
|
||||
releases = list(repo.get_releases())
|
||||
for release in releases:
|
||||
if release.tag_name == tag_name:
|
||||
break
|
||||
else:
|
||||
|
||||
def get_release():
|
||||
for i in range(RETRIES):
|
||||
releases = list(repo.get_releases())
|
||||
for release in releases:
|
||||
if release.tag_name == tag_name:
|
||||
return release
|
||||
print(f"Release for tag {repr(tag_name)} not found. Retrying...")
|
||||
time.sleep(1)
|
||||
raise RuntimeError("no release for tag " + repr(tag_name))
|
||||
|
||||
|
||||
release = get_release()
|
||||
|
||||
print("Uploading " + repr(asset_path) + "...")
|
||||
for i in range(RETRIES):
|
||||
try:
|
||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -1,13 +1,13 @@
|
|||
[package]
|
||||
name = "blake3"
|
||||
version = "1.3.1"
|
||||
version = "1.3.3"
|
||||
authors = ["Jack O'Connor <oconnor663@gmail.com>", "Samuel Neves"]
|
||||
description = "the BLAKE3 hash function"
|
||||
repository = "https://github.com/BLAKE3-team/BLAKE3"
|
||||
license = "CC0-1.0 OR Apache-2.0"
|
||||
documentation = "https://docs.rs/blake3"
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
@ -38,7 +38,9 @@ std = ["digest/std"]
|
|||
# "signature" crate.)
|
||||
traits-preview = ["digest"]
|
||||
|
||||
# ---------- Features below this line are for internal testing only. ----------
|
||||
# ---------- Features below this line are undocumented and unstable. ----------
|
||||
# The following features are mainly intended for testing and benchmarking, and
|
||||
# they might change or disappear at any time without a major version bump.
|
||||
|
||||
# By default on x86_64, this crate uses Samuel Neves' hand-written assembly
|
||||
# implementations for SSE4.1, AVX2, and AVX512. (These provide both the best
|
||||
|
@ -64,7 +66,7 @@ prefer_intrinsics = []
|
|||
#
|
||||
# As noted above, these flags are *for testing only* and are not stable. It's
|
||||
# possible that some users might find that their particular use case performs
|
||||
# better if e.g. AVX-512 is disabled, because of issues like CPU downlocking.
|
||||
# better if e.g. AVX-512 is disabled, because of issues like CPU downclocking.
|
||||
# If that comes up, and if disabling the instruction set here at the feature
|
||||
# level turns out to be the right approach, then we can design a stable
|
||||
# feature. Until then, we reserve the right to break these features in a patch
|
||||
|
@ -82,14 +84,14 @@ features = ["rayon"]
|
|||
[dependencies]
|
||||
arrayref = "0.3.5"
|
||||
arrayvec = { version = "0.7.0", default-features = false }
|
||||
constant_time_eq = "0.1.5"
|
||||
constant_time_eq = "0.2.4"
|
||||
rayon = { version = "1.2.1", optional = true }
|
||||
cfg-if = "1.0.0"
|
||||
digest = { version = "0.10.1", features = [ "mac" ], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4.2"
|
||||
page_size = "0.4.1"
|
||||
page_size = "0.5.0"
|
||||
rand = "0.8.0"
|
||||
rand_chacha = "0.3.0"
|
||||
reference_impl = { path = "./reference_impl" }
|
||||
|
|
|
@ -45,7 +45,7 @@ This repository is the official implementation of BLAKE3. It includes:
|
|||
|
||||
* The [C implementation](c), which like the Rust implementation includes
|
||||
SIMD code and runtime CPU feature detection on x86. Unlike the Rust
|
||||
implementation, it's not currently multithreaded. See
|
||||
implementation, it's [not currently multithreaded](c#multithreading). See
|
||||
[`c/README.md`](c/README.md).
|
||||
|
||||
* The [Rust reference implementation](reference_impl/reference_impl.rs),
|
||||
|
@ -200,11 +200,12 @@ Alternatively, it is licensed under the Apache License 2.0.
|
|||
|
||||
Here's a (non-exhaustive) list of protocols and software that use BLAKE3:
|
||||
|
||||
* [Alephium](https://github.com/alephium/alephium/blob/master/crypto/src/main/scala/org/alephium/crypto/Blake3.scala)
|
||||
* [Chia](https://github.com/Chia-Network/chia-blockchain/blob/main/CHANGELOG.md#10beta8-aka-beta-18---2020-07-16)
|
||||
* [IPFS](https://github.com/ipfs/go-verifcid/issues/13)
|
||||
* [LLVM](https://reviews.llvm.org/D121510)
|
||||
* [Nym](https://github.com/nymtech/nym/blob/59056a22c5e6b01a38da2124662bd1fa3c8abef2/common/nymsphinx/params/src/lib.rs#L5)
|
||||
* [OpenZFS](https://github.com/openzfs/zfs/pull/11897)
|
||||
* [OpenZFS](https://github.com/openzfs/zfs/)
|
||||
* [Redox](https://www.redox-os.org/news/pkgar-introduction/)
|
||||
* [Skale](https://github.com/skalenetwork/skale-consensus/pull/284)
|
||||
* [Solana](https://docs.rs/solana-program/1.9.5/solana_program/blake3/index.html)
|
||||
|
|
|
@ -4,9 +4,9 @@ version = 3
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.56"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
|
@ -20,17 +20,6 @@ version = "0.7.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -39,7 +28,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||
|
||||
[[package]]
|
||||
name = "b3sum"
|
||||
version = "1.3.1"
|
||||
version = "1.3.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"blake3",
|
||||
|
@ -60,7 +49,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.3.1"
|
||||
version = "1.3.3"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
|
@ -73,18 +62,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
version = "1.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -94,30 +83,53 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.6"
|
||||
version = "4.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123"
|
||||
checksum = "0acbd8d28a0a60d7108d7ae850af6ba34cf2d1257fc646980e5f97ce14275966"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"indexmap",
|
||||
"os_str_bytes",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"is-terminal",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
"terminal_size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.4"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
|
||||
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
|
@ -125,9 +137,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
|
@ -136,33 +148,31 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.8"
|
||||
version = "0.9.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c"
|
||||
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.8"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.3"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
|
@ -170,9 +180,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
|
@ -193,24 +203,45 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.5"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
|
||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
|
@ -223,10 +254,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
|
@ -237,22 +268,21 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
|
@ -263,56 +293,84 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
name = "io-lifetimes"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074"
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e394faa0efb47f9f227f1cd89978f854542b318a6f64fa695489c9c993056656"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae5bc6e2eb41c9def29a3e0f1306382807764b9b53112030eff57435667352d"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"io-lifetimes 1.0.2",
|
||||
"rustix 0.36.3",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.121"
|
||||
version = "0.2.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
name = "linux-raw-sys"
|
||||
version = "0.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.5.3"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f"
|
||||
checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.1.19",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.10.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
|
@ -326,20 +384,58 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
|
@ -347,22 +443,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.12"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -376,6 +471,34 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.35.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes 0.7.5",
|
||||
"libc",
|
||||
"linux-raw-sys 0.0.46",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes 1.0.2",
|
||||
"libc",
|
||||
"linux-raw-sys 0.1.3",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
|
@ -404,6 +527,17 @@ version = "2.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
|
@ -428,10 +562,14 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.0"
|
||||
name = "terminal_size"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
checksum = "40ca90c434fd12083d1a6bdcbe9f92a14f96c8a1ba600ba451734ac334521f7a"
|
||||
dependencies = [
|
||||
"rustix 0.35.13",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
|
@ -439,6 +577,12 @@ version = "1.15.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
@ -447,9 +591,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
|
||||
[[package]]
|
||||
name = "wild"
|
||||
version = "2.0.4"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "035793abb854745033f01a07647a79831eba29ec0be377205f2a25b0aa830020"
|
||||
checksum = "05b116685a6be0c52f5a103334cbff26db643826c7b3735fc0a3ba9871310a74"
|
||||
dependencies = [
|
||||
"glob",
|
||||
]
|
||||
|
@ -484,3 +628,60 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
[package]
|
||||
name = "b3sum"
|
||||
version = "1.3.1"
|
||||
version = "1.3.3"
|
||||
authors = ["Jack O'Connor <oconnor663@gmail.com>"]
|
||||
description = "a command line implementation of the BLAKE3 hash function"
|
||||
repository = "https://github.com/BLAKE3-team/BLAKE3"
|
||||
license = "CC0-1.0 OR Apache-2.0"
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
neon = ["blake3/neon"]
|
||||
|
@ -16,7 +16,7 @@ pure = ["blake3/pure"]
|
|||
[dependencies]
|
||||
anyhow = "1.0.25"
|
||||
blake3 = { version = "1", path = "..", features = ["rayon"] }
|
||||
clap = "3.0.5"
|
||||
clap = { version = "4.0.8", features = ["derive", "wrap_help"] }
|
||||
hex = "0.4.0"
|
||||
memmap2 = "0.5.3"
|
||||
rayon = "1.2.1"
|
||||
|
|
|
@ -5,37 +5,23 @@ A command line utility for calculating
|
|||
Coreutils tools like `b2sum` or `md5sum`.
|
||||
|
||||
```
|
||||
b3sum 1.3.1
|
||||
Usage: b3sum [OPTIONS] [FILE]...
|
||||
|
||||
USAGE:
|
||||
b3sum [OPTIONS] [FILE]...
|
||||
Arguments:
|
||||
[FILE]... Files to hash, or checkfiles to check
|
||||
|
||||
ARGS:
|
||||
<FILE>... Files to hash, or checkfiles to check. When no file is given,
|
||||
or when - is given, read standard input.
|
||||
|
||||
OPTIONS:
|
||||
-c, --check Reads BLAKE3 sums from the [FILE]s and checks them
|
||||
--derive-key <CONTEXT> Uses the key derivation mode, with the given
|
||||
context string. Cannot be used with --keyed.
|
||||
-h, --help Print help information
|
||||
--keyed Uses the keyed mode. The secret key is read from standard
|
||||
input, and it must be exactly 32 raw bytes.
|
||||
-l, --length <LEN> The number of output bytes, prior to hex
|
||||
encoding (default 32)
|
||||
--no-mmap Disables memory mapping. Currently this also disables
|
||||
multithreading.
|
||||
--no-names Omits filenames in the output
|
||||
--num-threads <NUM> The maximum number of threads to use. By
|
||||
default, this is the number of logical cores.
|
||||
If this flag is omitted, or if its value is 0,
|
||||
RAYON_NUM_THREADS is also respected.
|
||||
--quiet Skips printing OK for each successfully verified file.
|
||||
Must be used with --check.
|
||||
--raw Writes raw output bytes to stdout, rather than hex.
|
||||
--no-names is implied. In this case, only a single
|
||||
input is allowed.
|
||||
-V, --version Print version information
|
||||
Options:
|
||||
-l, --length <LEN> The number of output bytes, before hex encoding [default: 32]
|
||||
--num-threads <NUM> The maximum number of threads to use
|
||||
--keyed Use the keyed mode
|
||||
--derive-key <CONTEXT> Use the key derivation mode, with the given context string
|
||||
--no-mmap Disable memory mapping
|
||||
--no-names Omit filenames in the output
|
||||
--raw Write raw output bytes to stdout, rather than hex
|
||||
-c, --check Read BLAKE3 sums from the [FILE]s and check them
|
||||
--quiet Skip printing OK for each successfully verified file
|
||||
-h, --help Print help information (use `--help` for more detail)
|
||||
-V, --version Print version information
|
||||
```
|
||||
|
||||
See also [this document about how the `--check` flag
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use anyhow::{bail, ensure, Context, Result};
|
||||
use clap::{Arg, Command};
|
||||
use anyhow::{bail, ensure, Result};
|
||||
use clap::Parser;
|
||||
use std::cmp;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
@ -12,124 +11,106 @@ mod unit_tests;
|
|||
|
||||
const NAME: &str = "b3sum";
|
||||
|
||||
const FILE_ARG: &str = "FILE";
|
||||
const DERIVE_KEY_ARG: &str = "derive-key";
|
||||
const DERIVE_KEY_ARG: &str = "derive_key";
|
||||
const KEYED_ARG: &str = "keyed";
|
||||
const LENGTH_ARG: &str = "length";
|
||||
const NO_MMAP_ARG: &str = "no-mmap";
|
||||
const NO_NAMES_ARG: &str = "no-names";
|
||||
const NUM_THREADS_ARG: &str = "num-threads";
|
||||
const NO_NAMES_ARG: &str = "no_names";
|
||||
const RAW_ARG: &str = "raw";
|
||||
const CHECK_ARG: &str = "check";
|
||||
const QUIET_ARG: &str = "quiet";
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, max_term_width(100))]
|
||||
struct Inner {
|
||||
/// Files to hash, or checkfiles to check
|
||||
///
|
||||
/// When no file is given, or when - is given, read standard input.
|
||||
file: Vec<PathBuf>,
|
||||
|
||||
/// The number of output bytes, before hex encoding
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
default_value_t = blake3::OUT_LEN as u64,
|
||||
value_name("LEN")
|
||||
)]
|
||||
length: u64,
|
||||
|
||||
/// The maximum number of threads to use
|
||||
///
|
||||
/// By default, this is the number of logical cores. If this flag is
|
||||
/// omitted, or if its value is 0, RAYON_NUM_THREADS is also respected.
|
||||
#[arg(long, value_name("NUM"))]
|
||||
num_threads: Option<usize>,
|
||||
|
||||
/// Use the keyed mode, reading the 32-byte key from stdin
|
||||
#[arg(long, requires("file"))]
|
||||
keyed: bool,
|
||||
|
||||
/// Use the key derivation mode, with the given context string
|
||||
///
|
||||
/// Cannot be used with --keyed.
|
||||
#[arg(long, value_name("CONTEXT"), conflicts_with(KEYED_ARG))]
|
||||
derive_key: Option<String>,
|
||||
|
||||
/// Disable memory mapping
|
||||
///
|
||||
/// Currently this also disables multithreading.
|
||||
#[arg(long)]
|
||||
no_mmap: bool,
|
||||
|
||||
/// Omit filenames in the output
|
||||
#[arg(long)]
|
||||
no_names: bool,
|
||||
|
||||
/// Write raw output bytes to stdout, rather than hex
|
||||
///
|
||||
/// --no-names is implied. In this case, only a single input is allowed.
|
||||
#[arg(long)]
|
||||
raw: bool,
|
||||
|
||||
/// Read BLAKE3 sums from the [FILE]s and check them
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
conflicts_with(DERIVE_KEY_ARG),
|
||||
conflicts_with(KEYED_ARG),
|
||||
conflicts_with(LENGTH_ARG),
|
||||
conflicts_with(RAW_ARG),
|
||||
conflicts_with(NO_NAMES_ARG)
|
||||
)]
|
||||
check: bool,
|
||||
|
||||
/// Skip printing OK for each successfully verified file
|
||||
///
|
||||
/// Must be used with --check.
|
||||
#[arg(long, requires(CHECK_ARG))]
|
||||
quiet: bool,
|
||||
}
|
||||
|
||||
struct Args {
|
||||
inner: clap::ArgMatches,
|
||||
inner: Inner,
|
||||
file_args: Vec<PathBuf>,
|
||||
base_hasher: blake3::Hasher,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
fn parse() -> Result<Self> {
|
||||
let inner = Command::new(NAME)
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.arg(
|
||||
Arg::new(FILE_ARG)
|
||||
.multiple_occurrences(true)
|
||||
.allow_invalid_utf8(true)
|
||||
.help(
|
||||
"Files to hash, or checkfiles to check. When no file is given,\n\
|
||||
or when - is given, read standard input.",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(LENGTH_ARG)
|
||||
.long(LENGTH_ARG)
|
||||
.short('l')
|
||||
.takes_value(true)
|
||||
.value_name("LEN")
|
||||
.help(
|
||||
"The number of output bytes, prior to hex\n\
|
||||
encoding (default 32)",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(NUM_THREADS_ARG)
|
||||
.long(NUM_THREADS_ARG)
|
||||
.takes_value(true)
|
||||
.value_name("NUM")
|
||||
.help(
|
||||
"The maximum number of threads to use. By\n\
|
||||
default, this is the number of logical cores.\n\
|
||||
If this flag is omitted, or if its value is 0,\n\
|
||||
RAYON_NUM_THREADS is also respected.",
|
||||
),
|
||||
)
|
||||
.arg(Arg::new(KEYED_ARG).long(KEYED_ARG).requires(FILE_ARG).help(
|
||||
"Uses the keyed mode. The secret key is read from standard\n\
|
||||
input, and it must be exactly 32 raw bytes.",
|
||||
))
|
||||
.arg(
|
||||
Arg::new(DERIVE_KEY_ARG)
|
||||
.long(DERIVE_KEY_ARG)
|
||||
.conflicts_with(KEYED_ARG)
|
||||
.takes_value(true)
|
||||
.value_name("CONTEXT")
|
||||
.help(
|
||||
"Uses the key derivation mode, with the given\n\
|
||||
context string. Cannot be used with --keyed.",
|
||||
),
|
||||
)
|
||||
.arg(Arg::new(NO_MMAP_ARG).long(NO_MMAP_ARG).help(
|
||||
"Disables memory mapping. Currently this also disables\n\
|
||||
multithreading.",
|
||||
))
|
||||
.arg(
|
||||
Arg::new(NO_NAMES_ARG)
|
||||
.long(NO_NAMES_ARG)
|
||||
.help("Omits filenames in the output"),
|
||||
)
|
||||
.arg(Arg::new(RAW_ARG).long(RAW_ARG).help(
|
||||
"Writes raw output bytes to stdout, rather than hex.\n\
|
||||
--no-names is implied. In this case, only a single\n\
|
||||
input is allowed.",
|
||||
))
|
||||
.arg(
|
||||
Arg::new(CHECK_ARG)
|
||||
.long(CHECK_ARG)
|
||||
.short('c')
|
||||
.conflicts_with(DERIVE_KEY_ARG)
|
||||
.conflicts_with(KEYED_ARG)
|
||||
.conflicts_with(LENGTH_ARG)
|
||||
.conflicts_with(RAW_ARG)
|
||||
.conflicts_with(NO_NAMES_ARG)
|
||||
.help("Reads BLAKE3 sums from the [FILE]s and checks them"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(QUIET_ARG)
|
||||
.long(QUIET_ARG)
|
||||
.requires(CHECK_ARG)
|
||||
.help(
|
||||
"Skips printing OK for each successfully verified file.\n\
|
||||
Must be used with --check.",
|
||||
),
|
||||
)
|
||||
// wild::args_os() is equivalent to std::env::args_os() on Unix,
|
||||
// but on Windows it adds support for globbing.
|
||||
.get_matches_from(wild::args_os());
|
||||
let file_args = if let Some(iter) = inner.values_of_os(FILE_ARG) {
|
||||
iter.map(|s| s.into()).collect()
|
||||
// wild::args_os() is equivalent to std::env::args_os() on Unix,
|
||||
// but on Windows it adds support for globbing.
|
||||
let inner = Inner::parse_from(wild::args_os());
|
||||
let file_args = if !inner.file.is_empty() {
|
||||
inner.file.clone()
|
||||
} else {
|
||||
vec!["-".into()]
|
||||
};
|
||||
if inner.is_present(RAW_ARG) && file_args.len() > 1 {
|
||||
if inner.raw && file_args.len() > 1 {
|
||||
bail!("Only one filename can be provided when using --raw");
|
||||
}
|
||||
let base_hasher = if inner.is_present(KEYED_ARG) {
|
||||
let base_hasher = if inner.keyed {
|
||||
// In keyed mode, since stdin is used for the key, we can't handle
|
||||
// `-` arguments. Input::open handles that case below.
|
||||
blake3::Hasher::new_keyed(&read_key_from_stdin()?)
|
||||
} else if let Some(context) = inner.value_of(DERIVE_KEY_ARG) {
|
||||
} else if let Some(ref context) = inner.derive_key {
|
||||
blake3::Hasher::new_derive_key(context)
|
||||
} else {
|
||||
blake3::Hasher::new()
|
||||
|
@ -141,48 +122,36 @@ impl Args {
|
|||
})
|
||||
}
|
||||
|
||||
fn num_threads(&self) -> Result<Option<usize>> {
|
||||
if let Some(num_threads_str) = self.inner.value_of(NUM_THREADS_ARG) {
|
||||
Ok(Some(
|
||||
num_threads_str
|
||||
.parse()
|
||||
.context("Failed to parse num threads.")?,
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
fn num_threads(&self) -> Option<usize> {
|
||||
self.inner.num_threads
|
||||
}
|
||||
|
||||
fn check(&self) -> bool {
|
||||
self.inner.is_present(CHECK_ARG)
|
||||
self.inner.check
|
||||
}
|
||||
|
||||
fn raw(&self) -> bool {
|
||||
self.inner.is_present(RAW_ARG)
|
||||
self.inner.raw
|
||||
}
|
||||
|
||||
fn no_mmap(&self) -> bool {
|
||||
self.inner.is_present(NO_MMAP_ARG)
|
||||
self.inner.no_mmap
|
||||
}
|
||||
|
||||
fn no_names(&self) -> bool {
|
||||
self.inner.is_present(NO_NAMES_ARG)
|
||||
self.inner.no_names
|
||||
}
|
||||
|
||||
fn len(&self) -> Result<u64> {
|
||||
if let Some(length) = self.inner.value_of(LENGTH_ARG) {
|
||||
length.parse::<u64>().context("Failed to parse length.")
|
||||
} else {
|
||||
Ok(blake3::OUT_LEN as u64)
|
||||
}
|
||||
fn len(&self) -> u64 {
|
||||
self.inner.length
|
||||
}
|
||||
|
||||
fn keyed(&self) -> bool {
|
||||
self.inner.is_present(KEYED_ARG)
|
||||
self.inner.keyed
|
||||
}
|
||||
|
||||
fn quiet(&self) -> bool {
|
||||
self.inner.is_present(QUIET_ARG)
|
||||
self.inner.quiet
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +276,7 @@ fn maybe_memmap_file(file: &File) -> Result<Option<memmap2::Mmap>> {
|
|||
|
||||
fn write_hex_output(mut output: blake3::OutputReader, args: &Args) -> Result<()> {
|
||||
// Encoding multiples of the block size is most efficient.
|
||||
let mut len = args.len()?;
|
||||
let mut len = args.len();
|
||||
let mut block = [0; blake3::guts::BLOCK_LEN];
|
||||
while len > 0 {
|
||||
output.fill(&mut block);
|
||||
|
@ -320,7 +289,7 @@ fn write_hex_output(mut output: blake3::OutputReader, args: &Args) -> Result<()>
|
|||
}
|
||||
|
||||
fn write_raw_output(output: blake3::OutputReader, args: &Args) -> Result<()> {
|
||||
let mut output = output.take(args.len()?);
|
||||
let mut output = output.take(args.len());
|
||||
let stdout = std::io::stdout();
|
||||
let mut handler = stdout.lock();
|
||||
std::io::copy(&mut output, &mut handler)?;
|
||||
|
@ -334,13 +303,13 @@ fn read_key_from_stdin() -> Result<[u8; blake3::KEY_LEN]> {
|
|||
.lock()
|
||||
.take(blake3::KEY_LEN as u64 + 1)
|
||||
.read_to_end(&mut bytes)?;
|
||||
if n < 32 {
|
||||
if n < blake3::KEY_LEN {
|
||||
bail!(
|
||||
"expected {} key bytes from stdin, found {}",
|
||||
blake3::KEY_LEN,
|
||||
n,
|
||||
)
|
||||
} else if n > 32 {
|
||||
} else if n > blake3::KEY_LEN {
|
||||
bail!("read more than {} key bytes from stdin", blake3::KEY_LEN)
|
||||
} else {
|
||||
Ok(bytes[..blake3::KEY_LEN].try_into().unwrap())
|
||||
|
@ -520,8 +489,8 @@ fn hash_one_input(path: &Path, args: &Args) -> Result<()> {
|
|||
}
|
||||
|
||||
// Returns true for success. Having a boolean return value here, instead of
|
||||
// passing down the some_file_failed reference, makes it less likely that we
|
||||
// might forget to set it in some error condition.
|
||||
// passing down the files_failed reference, makes it less likely that we might
|
||||
// forget to set it in some error condition.
|
||||
fn check_one_line(line: &str, args: &Args) -> bool {
|
||||
let parse_result = parse_check_line(&line);
|
||||
let ParsedCheckLine {
|
||||
|
@ -567,7 +536,7 @@ fn check_one_line(line: &str, args: &Args) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_one_checkfile(path: &Path, args: &Args, some_file_failed: &mut bool) -> Result<()> {
|
||||
fn check_one_checkfile(path: &Path, args: &Args, files_failed: &mut u64) -> Result<()> {
|
||||
let checkfile_input = Input::open(path, args)?;
|
||||
let mut bufreader = io::BufReader::new(checkfile_input);
|
||||
let mut line = String::new();
|
||||
|
@ -581,7 +550,9 @@ fn check_one_checkfile(path: &Path, args: &Args, some_file_failed: &mut bool) ->
|
|||
// return, so it doesn't return a Result.
|
||||
let success = check_one_line(&line, args);
|
||||
if !success {
|
||||
*some_file_failed = true;
|
||||
// We use `files_failed > 0` to indicate a mismatch, so it's important for correctness
|
||||
// that it's impossible for this counter to overflow.
|
||||
*files_failed = files_failed.saturating_add(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -589,21 +560,16 @@ fn check_one_checkfile(path: &Path, args: &Args, some_file_failed: &mut bool) ->
|
|||
fn main() -> Result<()> {
|
||||
let args = Args::parse()?;
|
||||
let mut thread_pool_builder = rayon::ThreadPoolBuilder::new();
|
||||
if let Some(num_threads) = args.num_threads()? {
|
||||
if let Some(num_threads) = args.num_threads() {
|
||||
thread_pool_builder = thread_pool_builder.num_threads(num_threads);
|
||||
}
|
||||
let thread_pool = thread_pool_builder.build()?;
|
||||
thread_pool.install(|| {
|
||||
let mut some_file_failed = false;
|
||||
let mut files_failed = 0u64;
|
||||
// Note that file_args automatically includes `-` if nothing is given.
|
||||
for path in &args.file_args {
|
||||
if args.check() {
|
||||
// A hash mismatch or a failure to read a hashed file will be
|
||||
// printed in the checkfile loop, and will not propagate here.
|
||||
// This is similar to the explicit error handling we do in the
|
||||
// hashing case immediately below. In these cases,
|
||||
// some_file_failed will be set to false.
|
||||
check_one_checkfile(path, &args, &mut some_file_failed)?;
|
||||
check_one_checkfile(path, &args, &mut files_failed)?;
|
||||
} else {
|
||||
// Errors encountered in hashing are tolerated and printed to
|
||||
// stderr. This allows e.g. `b3sum *` to print errors for
|
||||
|
@ -611,11 +577,29 @@ fn main() -> Result<()> {
|
|||
// errors we'll still return non-zero at the end.
|
||||
let result = hash_one_input(path, &args);
|
||||
if let Err(e) = result {
|
||||
some_file_failed = true;
|
||||
files_failed = files_failed.saturating_add(1);
|
||||
eprintln!("{}: {}: {}", NAME, path.to_string_lossy(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::process::exit(if some_file_failed { 1 } else { 0 });
|
||||
if args.check() && files_failed > 0 {
|
||||
eprintln!(
|
||||
"{}: WARNING: {} computed checksum{} did NOT match",
|
||||
NAME,
|
||||
files_failed,
|
||||
if files_failed == 1 { "" } else { "s" },
|
||||
);
|
||||
}
|
||||
std::process::exit(if files_failed > 0 { 1 } else { 0 });
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use clap::CommandFactory;
|
||||
|
||||
#[test]
|
||||
fn test_args() {
|
||||
crate::Inner::command().debug_assert();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,23 @@ fn test_keyed() {
|
|||
.read()
|
||||
.unwrap();
|
||||
assert_eq!(&*expected, &*output);
|
||||
|
||||
// Make sure that keys of the wrong length lead to errors.
|
||||
for bad_length in [0, 1, blake3::KEY_LEN - 1, blake3::KEY_LEN + 1] {
|
||||
dbg!(bad_length);
|
||||
let output = cmd!(b3sum_exe(), "--keyed", f.path())
|
||||
.stdin_bytes(vec![0; bad_length])
|
||||
.stdout_capture()
|
||||
.stderr_capture()
|
||||
.unchecked()
|
||||
.run()
|
||||
.unwrap();
|
||||
assert!(!output.status.success());
|
||||
assert!(output.stdout.is_empty());
|
||||
// Make sure the error message is relevant.
|
||||
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||
assert!(stderr.contains("key bytes"));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -411,7 +428,10 @@ fn test_check() {
|
|||
c/d: OK\n";
|
||||
assert!(!output.status.success());
|
||||
assert_eq!(expected_check_failure, stdout);
|
||||
assert_eq!("", stderr);
|
||||
assert_eq!(
|
||||
"b3sum: WARNING: 1 computed checksum did NOT match\n",
|
||||
stderr,
|
||||
);
|
||||
|
||||
// Delete one of the files and check again.
|
||||
fs::remove_file(dir.path().join("b")).unwrap();
|
||||
|
@ -433,7 +453,10 @@ fn test_check() {
|
|||
);
|
||||
assert!(!output.status.success());
|
||||
assert_eq!(expected_check_failure, stdout);
|
||||
assert_eq!("", stderr);
|
||||
assert_eq!(
|
||||
"b3sum: WARNING: 1 computed checksum did NOT match\n",
|
||||
stderr,
|
||||
);
|
||||
|
||||
// Confirm that --quiet suppresses the OKs but not the FAILEDs.
|
||||
let output = cmd!(b3sum_exe(), "--check", "--quiet", &checkfile_path)
|
||||
|
@ -448,7 +471,10 @@ fn test_check() {
|
|||
let expected_check_failure = format!("b: FAILED ({})\n", open_file_error);
|
||||
assert!(!output.status.success());
|
||||
assert_eq!(expected_check_failure, stdout);
|
||||
assert_eq!("", stderr);
|
||||
assert_eq!(
|
||||
"b3sum: WARNING: 1 computed checksum did NOT match\n",
|
||||
stderr,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -463,9 +489,12 @@ fn test_check_invalid_characters() {
|
|||
.unwrap();
|
||||
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||
let expected_stderr = "\
|
||||
b3sum: Null character in path\n\
|
||||
b3sum: WARNING: 1 computed checksum did NOT match\n";
|
||||
assert!(!output.status.success());
|
||||
assert_eq!("", stdout);
|
||||
assert_eq!("b3sum: Null character in path\n", stderr);
|
||||
assert_eq!(expected_stderr, stderr);
|
||||
|
||||
// Check that a Unicode replacement character in the path fails.
|
||||
let output = cmd!(b3sum_exe(), "--check")
|
||||
|
@ -477,9 +506,12 @@ fn test_check_invalid_characters() {
|
|||
.unwrap();
|
||||
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||
let expected_stderr = "\
|
||||
b3sum: Unicode replacement character in path\n\
|
||||
b3sum: WARNING: 1 computed checksum did NOT match\n";
|
||||
assert!(!output.status.success());
|
||||
assert_eq!("", stdout);
|
||||
assert_eq!("b3sum: Unicode replacement character in path\n", stderr);
|
||||
assert_eq!(expected_stderr, stderr);
|
||||
|
||||
// Check that an invalid escape sequence in the path fails.
|
||||
let output = cmd!(b3sum_exe(), "--check")
|
||||
|
@ -491,9 +523,12 @@ fn test_check_invalid_characters() {
|
|||
.unwrap();
|
||||
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||
let expected_stderr = "\
|
||||
b3sum: Invalid backslash escape\n\
|
||||
b3sum: WARNING: 1 computed checksum did NOT match\n";
|
||||
assert!(!output.status.success());
|
||||
assert_eq!("", stdout);
|
||||
assert_eq!("b3sum: Invalid backslash escape\n", stderr);
|
||||
assert_eq!(expected_stderr, stderr);
|
||||
|
||||
// Windows also forbids literal backslashes. Check for that if and only if
|
||||
// we're on Windows.
|
||||
|
@ -507,9 +542,12 @@ fn test_check_invalid_characters() {
|
|||
.unwrap();
|
||||
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||
let expected_stderr = "\
|
||||
b3sum: Backslash in path\n\
|
||||
b3sum: WARNING: 1 computed checksum did NOT match\n";
|
||||
assert!(!output.status.success());
|
||||
assert_eq!("", stdout);
|
||||
assert_eq!("b3sum: Backslash in path\n", stderr);
|
||||
assert_eq!(expected_stderr, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
15
c/README.md
15
c/README.md
|
@ -196,14 +196,13 @@ BLAKE3 output is intended to provide N bits of first and second preimage resista
|
|||
bits of collision resistance, for any N up to 256. Longer outputs don't provide any additional
|
||||
security.
|
||||
|
||||
Avoid relying on the secrecy of the output offset, that is, the number of output bytes read or
|
||||
the arguments to [`seek`](struct.OutputReader.html#method.seek) or
|
||||
[`set_position`](struct.OutputReader.html#method.set_position). [_Block-Cipher-Based Tree
|
||||
Hashing_ by Aldo Gunsing](https://eprint.iacr.org/2022/283) shows that an attacker who knows
|
||||
both the message and the key (if any) can easily determine the offset of an extended output.
|
||||
For comparison, AES-CTR has a similar property: if you know the key, you can decrypt a block
|
||||
from an unknown position in the output stream to recover its block index. Callers with strong
|
||||
secret keys aren't affected in practice, but secret offsets are a [design
|
||||
Avoid relying on the secrecy of the output offset, that is, the `seek` argument of
|
||||
`blake3_hasher_finalize_seek`. [_Block-Cipher-Based Tree Hashing_ by Aldo
|
||||
Gunsing](https://eprint.iacr.org/2022/283) shows that an attacker who knows both the message
|
||||
and the key (if any) can easily determine the offset of an extended output. For comparison,
|
||||
AES-CTR has a similar property: if you know the key, you can decrypt a block from an unknown
|
||||
position in the output stream to recover its block index. Callers with strong secret keys
|
||||
aren't affected in practice, but secret offsets are a [design
|
||||
smell](https://en.wikipedia.org/wiki/Design_smell) in any case.
|
||||
|
||||
# Building
|
||||
|
|
|
@ -246,7 +246,7 @@ INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values,
|
|||
|
||||
// The wide helper function returns (writes out) an array of chaining values
|
||||
// and returns the length of that array. The number of chaining values returned
|
||||
// is the dyanmically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,
|
||||
// is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,
|
||||
// if the input is shorter than that many chunks. The reason for maintaining a
|
||||
// wide array of chaining values going back up the tree, is to allow the
|
||||
// implementation to hash as many parents in parallel as possible.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLAKE3_VERSION_STRING "1.3.1"
|
||||
#define BLAKE3_VERSION_STRING "1.3.3"
|
||||
#define BLAKE3_KEY_LEN 32
|
||||
#define BLAKE3_OUT_LEN 32
|
||||
#define BLAKE3_BLOCK_LEN 64
|
||||
|
|
|
@ -1784,7 +1784,7 @@ blake3_hash_many_avx2:
|
|||
vmovdqu xmmword ptr [rbx+0x10], xmm1
|
||||
jmp 4b
|
||||
|
||||
.section .rodata
|
||||
.section .rdata
|
||||
.p2align 6
|
||||
ADD0:
|
||||
.long 0, 1, 2, 3, 4, 5, 6, 7
|
||||
|
|
|
@ -1047,13 +1047,26 @@ INLINE void transpose_msg_vecs16(const uint8_t *const *inputs,
|
|||
INLINE void load_counters16(uint64_t counter, bool increment_counter,
|
||||
__m512i *out_lo, __m512i *out_hi) {
|
||||
const __m512i mask = _mm512_set1_epi32(-(int32_t)increment_counter);
|
||||
const __m512i add0 = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
|
||||
const __m512i add1 = _mm512_and_si512(mask, add0);
|
||||
__m512i l = _mm512_add_epi32(_mm512_set1_epi32((int32_t)counter), add1);
|
||||
__mmask16 carry = _mm512_cmp_epu32_mask(l, add1, _MM_CMPINT_LT);
|
||||
__m512i h = _mm512_mask_add_epi32(_mm512_set1_epi32((int32_t)(counter >> 32)), carry, _mm512_set1_epi32((int32_t)(counter >> 32)), _mm512_set1_epi32(1));
|
||||
*out_lo = l;
|
||||
*out_hi = h;
|
||||
const __m512i deltas = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
|
||||
const __m512i masked_deltas = _mm512_and_si512(deltas, mask);
|
||||
const __m512i low_words = _mm512_add_epi32(
|
||||
_mm512_set1_epi32((int32_t)counter),
|
||||
masked_deltas);
|
||||
// The carry bit is 1 if the high bit of the word was 1 before addition and is
|
||||
// 0 after.
|
||||
// NOTE: It would be a bit more natural to use _mm512_cmp_epu32_mask to
|
||||
// compute the carry bits here, and originally we did, but that intrinsic is
|
||||
// broken under GCC 5.4. See https://github.com/BLAKE3-team/BLAKE3/issues/271.
|
||||
const __m512i carries = _mm512_srli_epi32(
|
||||
_mm512_andnot_si512(
|
||||
low_words, // 0 after (gets inverted by andnot)
|
||||
_mm512_set1_epi32((int32_t)counter)), // and 1 before
|
||||
31);
|
||||
const __m512i high_words = _mm512_add_epi32(
|
||||
_mm512_set1_epi32((int32_t)(counter >> 32)),
|
||||
carries);
|
||||
*out_lo = low_words;
|
||||
*out_hi = high_words;
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -2587,7 +2587,7 @@ blake3_compress_xof_avx512:
|
|||
add rsp, 72
|
||||
ret
|
||||
|
||||
.section .rodata
|
||||
.section .rdata
|
||||
.p2align 6
|
||||
INDEX0:
|
||||
.long 0, 1, 2, 3, 16, 17, 18, 19
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
name = "blake3_c_rust_bindings"
|
||||
version = "0.0.0"
|
||||
description = "TESTING ONLY Rust bindings for the BLAKE3 C implementation"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
# By default the x86-64 build uses assembly implementations. This feature makes
|
||||
|
|
|
@ -207,99 +207,107 @@ type HashManyFn = unsafe extern "C" fn(
|
|||
|
||||
// A shared helper function for platform-specific tests.
|
||||
pub fn test_hash_many_fn(hash_many_fn: HashManyFn) {
|
||||
// 31 (16 + 8 + 4 + 2 + 1) inputs
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
// A counter just prior to u32::MAX.
|
||||
let counter = (1u64 << 32) - 1;
|
||||
// Test a few different initial counter values.
|
||||
// - 0: The base case.
|
||||
// - u32::MAX: The low word of the counter overflows for all inputs except the first.
|
||||
// - i32::MAX: *No* overflow. But carry bugs in tricky SIMD code can screw this up, if you XOR
|
||||
// when you're supposed to ANDNOT...
|
||||
let initial_counters = [0, u32::MAX as u64, i32::MAX as u64];
|
||||
for counter in initial_counters {
|
||||
dbg!(counter);
|
||||
|
||||
// First hash chunks.
|
||||
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
chunks.push(array_ref!(input_buf, i * CHUNK_LEN, CHUNK_LEN));
|
||||
}
|
||||
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
crate::ffi::blake3_hash_many_portable(
|
||||
chunks.as_ptr() as _,
|
||||
chunks.len(),
|
||||
CHUNK_LEN / BLOCK_LEN,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
true,
|
||||
KEYED_HASH,
|
||||
CHUNK_START,
|
||||
CHUNK_END,
|
||||
portable_chunks_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
// 31 (16 + 8 + 4 + 2 + 1) inputs
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
|
||||
let mut test_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_fn(
|
||||
chunks.as_ptr() as _,
|
||||
chunks.len(),
|
||||
CHUNK_LEN / BLOCK_LEN,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
true,
|
||||
KEYED_HASH,
|
||||
CHUNK_START,
|
||||
CHUNK_END,
|
||||
test_chunks_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_chunks_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_chunks_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
}
|
||||
// First hash chunks.
|
||||
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
chunks.push(array_ref!(input_buf, i * CHUNK_LEN, CHUNK_LEN));
|
||||
}
|
||||
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
crate::ffi::blake3_hash_many_portable(
|
||||
chunks.as_ptr() as _,
|
||||
chunks.len(),
|
||||
CHUNK_LEN / BLOCK_LEN,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
true,
|
||||
KEYED_HASH,
|
||||
CHUNK_START,
|
||||
CHUNK_END,
|
||||
portable_chunks_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
// Then hash parents.
|
||||
let mut parents = ArrayVec::<&[u8; 2 * OUT_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
parents.push(array_ref!(input_buf, i * 2 * OUT_LEN, 2 * OUT_LEN));
|
||||
}
|
||||
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
crate::ffi::blake3_hash_many_portable(
|
||||
parents.as_ptr() as _,
|
||||
parents.len(),
|
||||
1,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
false,
|
||||
KEYED_HASH | PARENT,
|
||||
0,
|
||||
0,
|
||||
portable_parents_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
let mut test_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_fn(
|
||||
chunks.as_ptr() as _,
|
||||
chunks.len(),
|
||||
CHUNK_LEN / BLOCK_LEN,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
true,
|
||||
KEYED_HASH,
|
||||
CHUNK_START,
|
||||
CHUNK_END,
|
||||
test_chunks_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_chunks_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_chunks_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
}
|
||||
|
||||
let mut test_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_fn(
|
||||
parents.as_ptr() as _,
|
||||
parents.len(),
|
||||
1,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
false,
|
||||
KEYED_HASH | PARENT,
|
||||
0,
|
||||
0,
|
||||
test_parents_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_parents_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_parents_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
// Then hash parents.
|
||||
let mut parents = ArrayVec::<&[u8; 2 * OUT_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
parents.push(array_ref!(input_buf, i * 2 * OUT_LEN, 2 * OUT_LEN));
|
||||
}
|
||||
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
crate::ffi::blake3_hash_many_portable(
|
||||
parents.as_ptr() as _,
|
||||
parents.len(),
|
||||
1,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
false,
|
||||
KEYED_HASH | PARENT,
|
||||
0,
|
||||
0,
|
||||
portable_parents_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut test_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_fn(
|
||||
parents.as_ptr() as _,
|
||||
parents.len(),
|
||||
1,
|
||||
TEST_KEY_WORDS.as_ptr(),
|
||||
counter,
|
||||
false,
|
||||
KEYED_HASH | PARENT,
|
||||
0,
|
||||
0,
|
||||
test_parents_out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_parents_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_parents_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#elif defined(__GNUC__)
|
||||
#include <immintrin.h>
|
||||
#else
|
||||
#error "Unimplemented!"
|
||||
#undef IS_X86 /* Unimplemented! */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -101,7 +101,7 @@ static
|
|||
if (*edx & (1UL << 26))
|
||||
features |= SSE2;
|
||||
#endif
|
||||
if (*ecx & (1UL << 0))
|
||||
if (*ecx & (1UL << 9))
|
||||
features |= SSSE3;
|
||||
if (*ecx & (1UL << 19))
|
||||
features |= SSE41;
|
||||
|
|
|
@ -46,7 +46,6 @@ enum blake3_flags {
|
|||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#if !defined(BLAKE3_USE_NEON)
|
||||
|
@ -88,7 +87,7 @@ static const uint8_t MSG_SCHEDULE[7][16] = {
|
|||
/* x is assumed to be nonzero. */
|
||||
static unsigned int highest_one(uint64_t x) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return 63 ^ __builtin_clzll(x);
|
||||
return 63 ^ (unsigned int)__builtin_clzll(x);
|
||||
#elif defined(_MSC_VER) && defined(IS_X86_64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, x);
|
||||
|
@ -118,7 +117,7 @@ static unsigned int highest_one(uint64_t x) {
|
|||
// Count the number of 1 bits.
|
||||
INLINE unsigned int popcnt(uint64_t x) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_popcountll(x);
|
||||
return (unsigned int)__builtin_popcountll(x);
|
||||
#else
|
||||
unsigned int count = 0;
|
||||
while (x != 0) {
|
||||
|
|
|
@ -2301,7 +2301,7 @@ blake3_compress_xof_sse2:
|
|||
ret
|
||||
|
||||
|
||||
.section .rodata
|
||||
.section .rdata
|
||||
.p2align 6
|
||||
BLAKE3_IV:
|
||||
.long 0x6A09E667, 0xBB67AE85
|
||||
|
|
|
@ -2042,7 +2042,7 @@ blake3_compress_xof_sse41:
|
|||
ret
|
||||
|
||||
|
||||
.section .rodata
|
||||
.section .rdata
|
||||
.p2align 6
|
||||
BLAKE3_IV:
|
||||
.long 0x6A09E667, 0xBB67AE85
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "reference_impl"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "reference_impl"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
//! ```
|
||||
|
||||
use core::cmp::min;
|
||||
use core::convert::TryInto;
|
||||
|
||||
const OUT_LEN: usize = 32;
|
||||
const KEY_LEN: usize = 32;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
//! let mut output = [0; 1000];
|
||||
//! let mut output_reader = hasher.finalize_xof();
|
||||
//! output_reader.fill(&mut output);
|
||||
//! assert_eq!(&output[..32], hash1.as_bytes());
|
||||
//! assert_eq!(hash1, output[..32]);
|
||||
//! # }
|
||||
//!
|
||||
//! // Print a hash as hex.
|
||||
|
@ -659,7 +659,7 @@ fn compress_parents_parallel(
|
|||
|
||||
// The wide helper function returns (writes out) an array of chaining values
|
||||
// and returns the length of that array. The number of chaining values returned
|
||||
// is the dyanmically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,
|
||||
// is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,
|
||||
// if the input is shorter than that many chunks. The reason for maintaining a
|
||||
// wide array of chaining values going back up the tree, is to allow the
|
||||
// implementation to hash as many parents in parallel as possible.
|
||||
|
|
139
src/test.rs
139
src/test.rs
|
@ -111,89 +111,98 @@ pub fn test_hash_many_fn(
|
|||
hash_many_chunks_fn: HashManyFn<[u8; CHUNK_LEN]>,
|
||||
hash_many_parents_fn: HashManyFn<[u8; 2 * OUT_LEN]>,
|
||||
) {
|
||||
// 31 (16 + 8 + 4 + 2 + 1) inputs
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
// A counter just prior to u32::MAX.
|
||||
let counter = (1u64 << 32) - 1;
|
||||
// Test a few different initial counter values.
|
||||
// - 0: The base case.
|
||||
// - u32::MAX: The low word of the counter overflows for all inputs except the first.
|
||||
// - i32::MAX: *No* overflow. But carry bugs in tricky SIMD code can screw this up, if you XOR
|
||||
// when you're supposed to ANDNOT...
|
||||
let initial_counters = [0, u32::MAX as u64, i32::MAX as u64];
|
||||
for counter in initial_counters {
|
||||
#[cfg(feature = "std")]
|
||||
dbg!(counter);
|
||||
|
||||
// First hash chunks.
|
||||
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
chunks.push(array_ref!(input_buf, i * CHUNK_LEN, CHUNK_LEN));
|
||||
}
|
||||
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
crate::portable::hash_many(
|
||||
&chunks,
|
||||
&TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::Yes,
|
||||
crate::KEYED_HASH,
|
||||
crate::CHUNK_START,
|
||||
crate::CHUNK_END,
|
||||
&mut portable_chunks_out,
|
||||
);
|
||||
// 31 (16 + 8 + 4 + 2 + 1) inputs
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
|
||||
let mut test_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_chunks_fn(
|
||||
&chunks[..],
|
||||
// First hash chunks.
|
||||
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
chunks.push(array_ref!(input_buf, i * CHUNK_LEN, CHUNK_LEN));
|
||||
}
|
||||
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
crate::portable::hash_many(
|
||||
&chunks,
|
||||
&TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::Yes,
|
||||
crate::KEYED_HASH,
|
||||
crate::CHUNK_START,
|
||||
crate::CHUNK_END,
|
||||
&mut test_chunks_out,
|
||||
&mut portable_chunks_out,
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
#[cfg(feature = "std")]
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_chunks_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_chunks_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
}
|
||||
|
||||
// Then hash parents.
|
||||
let mut parents = ArrayVec::<&[u8; 2 * OUT_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
parents.push(array_ref!(input_buf, i * 2 * OUT_LEN, 2 * OUT_LEN));
|
||||
}
|
||||
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
crate::portable::hash_many(
|
||||
&parents,
|
||||
&TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::No,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
0,
|
||||
0,
|
||||
&mut portable_parents_out,
|
||||
);
|
||||
let mut test_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_chunks_fn(
|
||||
&chunks[..],
|
||||
&TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::Yes,
|
||||
crate::KEYED_HASH,
|
||||
crate::CHUNK_START,
|
||||
crate::CHUNK_END,
|
||||
&mut test_chunks_out,
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
#[cfg(feature = "std")]
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_chunks_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_chunks_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
}
|
||||
|
||||
let mut test_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_parents_fn(
|
||||
&parents[..],
|
||||
// Then hash parents.
|
||||
let mut parents = ArrayVec::<&[u8; 2 * OUT_LEN], NUM_INPUTS>::new();
|
||||
for i in 0..NUM_INPUTS {
|
||||
parents.push(array_ref!(input_buf, i * 2 * OUT_LEN, 2 * OUT_LEN));
|
||||
}
|
||||
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
crate::portable::hash_many(
|
||||
&parents,
|
||||
&TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::No,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
0,
|
||||
0,
|
||||
&mut test_parents_out,
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
#[cfg(feature = "std")]
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_parents_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_parents_out[n * OUT_LEN..][..OUT_LEN]
|
||||
&mut portable_parents_out,
|
||||
);
|
||||
|
||||
let mut test_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
unsafe {
|
||||
hash_many_parents_fn(
|
||||
&parents[..],
|
||||
&TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::No,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
0,
|
||||
0,
|
||||
&mut test_parents_out,
|
||||
);
|
||||
}
|
||||
for n in 0..NUM_INPUTS {
|
||||
#[cfg(feature = "std")]
|
||||
dbg!(n);
|
||||
assert_eq!(
|
||||
&portable_parents_out[n * OUT_LEN..][..OUT_LEN],
|
||||
&test_parents_out[n * OUT_LEN..][..OUT_LEN]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "test_vectors"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
neon = ["blake3/neon"]
|
||||
|
|
|
@ -142,7 +142,6 @@ pub fn parse_test_cases() -> Cases {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::convert::TryInto;
|
||||
|
||||
fn test_reference_impl_all_at_once(
|
||||
key: &[u8; blake3::KEY_LEN],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "compiler_version"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.50"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "instruction_set_support"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
- Bump the version in the root Cargo.toml.
|
||||
- Bump the version in b3sum/Cargo.toml.
|
||||
- Delete b3sum/Cargo.lock and recreate it with `cargo build` or similar.
|
||||
- Update the `--help` output (including the version number) in b3sum/README.md.
|
||||
- Update the `--help` output in b3sum/README.md if it's changed.
|
||||
- Bump `BLAKE3_VERSION_STRING` in c/blake3.h.
|
||||
- Make a version bump commit with change notes.
|
||||
- `git push` and make sure CI is green.
|
||||
|
|
Loading…
Reference in New Issue