Skip to content

➿ Pure Go/ASM implementation of CryptoNight hash function with its variants, without any CGO binding.

License

Notifications You must be signed in to change notification settings

ngchain/cryptonight

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cryptonight

GoDoc tag CircleCI Codecov Go Report Card License

Pure Go/ASM implementation of CryptoNight hash function and some of its variant, without any CGO binding.

Features

  • Support v0, v1, v2 variants.

  • No CGO hell, making builds easier and faster.

  • Hardware acceleration available for amd64 architecture.

  • Use of an internal sync.Pool to manage caches, since it is memory hard.

Install

$ go get -u ekyu.moe/cryptonight

A simple CLI utility is also available with go get -u ekyu.moe/cryptonight/cmd/cnhash.

Usage of cnhash:
  -bench
        Benchmark mode, don't do anything else.
  -in-file string
        Read input from file instead of stdin.
  -in-hex
        Read input in hex instead of binary.
  -include-diff
        Append the difficulty of the result hash to the output. If -out-binary is not given,
the difficulty will be appeneded to the output in decimal with comma separated (CSV friendly)
, otherwise it will be appeneded to the hash binary (which is 32 bytes long) directly, in 8
bytes little endian.
  -out-binary
        Produce output in binary (little endian) instead of hex.
  -out-file string
        Produce output to file instead of stdout.
  -variant int
        Set CryptoNight variant, default 0. This applies to benchmark mode as well.

Example

package main

import (
    "fmt"

    "ekyu.moe/cryptonight"
)

func main() {
    blob := []byte("Hello, 世界")
    fmt.Printf("%x\n", cryptonight.Sum(blob, 0)) // original
    // Output: 0999794e4e20d86e6a81b54495aeb370b6a9ae795fb5af4f778afaf07c0b2e0e

    blob = []byte("variant 1 requires at least 43 bytes of input.")
    fmt.Printf("%x\n", cryptonight.Sum(blob, 1)) // variant 1
    // Output: 261124c5a6dca5d4aa3667d328a94ead9a819ae714e1f1dc113ceeb14f1ecf99

    blob = []byte("Monero is cash for a connected world. It’s fast, private, and secure.")
    fmt.Printf("%x\n", cryptonight.Sum(blob, 2)) // variant 2
    // Output: abb61f40468c70234051e4bb5e8b670812473b2a71e02c9633ef94996a621b96
}

Tested architectures

  • amd64 (w/ AVX, SSE, AES)

  • amd64 (w/o AVX, SSE, AES)

  • 386

  • arm64

Benchmarks

CPU: 4 x Intel® Xeon® CPU E3-1270 v3 @ 3.50GHz

goos: linux
goarch: amd64
pkg: ekyu.moe/cryptonight
BenchmarkSum/v0-4            100   20208070 ns/op   21584 B/op   2 allocs/op
BenchmarkSum/v1-4            100   20535318 ns/op   21584 B/op   2 allocs/op
BenchmarkSum/v2-4            100   22328893 ns/op   21584 B/op   2 allocs/op
BenchmarkSum/v0-parallel-4   100   10798945 ns/op   42664 B/op   2 allocs/op
BenchmarkSum/v1-parallel-4   100   10316040 ns/op   42655 B/op   2 allocs/op
BenchmarkSum/v2-parallel-4   100   11740615 ns/op   42661 B/op   2 allocs/op
PASS

Development

While this repository is already out-of-box, which means what you need to do to use it in your code is just a go get (or dep ensure -add whatsoever), in case you want to hack on this library, some additional steps are required since it uses code generation.

Preprocess

If you modified a source file in this library that uses C-kind macros (the comments tells), in order to expand them and generate the final code, cpp(1) is needed, which a part of GCC toolchain and should be already available if you have installed gcc (or MinGW for Windows) in your machine.

Once some modification is made in a file that used macro, simply use go generate ekyu.moe/cryptonight/... to run the gcc preprocessor on them.

Packages information

ekyu.moe/cryptonight/internal/aes

From Go’s crypto/aes. Since CryptoNight’s use of AES is quite non-standard and not intended for encryption, you must use this package this package with care for project that’s not CryptoNight associated.

ekyu.moe/cryptonight/internal/sha3

From Go’s golang.org/x/crypto/sha3. All CryptoNight specific additional works are made in cn.go only; other files are untouched at all.

ekyu.moe/cryptonight/groestl

Grøstl-256 implementation. It is directly ported from C and not quite optimized.

ekyu.moe/cryptonight/jh

JH-256 implementation. It is directly ported from C and not quite optimized.

Tests, coverage and benchmarks

$ go test -v -race -coverprofile=coverage.txt -covermode=atomic
$ go tool cover -html=coverage.txt
$ go test -v -run=^$ -bench=. -benchmem

TODO

  • ❏ ARM64-specific optimization

  • ✓ Tests on other architectures

  • ✓ Improve performance for variant 2

  • ❏ Improve performance for groestl and jh

  • ✓ Try a nearly full assembly implementation (except for the final hash) for amd64

Donation

If you find this lib helpful, maybe consider buying me a cup of coffee at

XMR

4777777jHFbZB4gyqrB1JHDtrGFusyj4b3M2nScYDPKEM133ng2QDrK9ycqizXS2XofADw5do5rU19LQmpTGCfeQTerm1Ti

BTC

1Eqqqq9xR78wJyRXXgvR73HEfKdEwq68BT

Much thanks.

License

MIT

About

➿ Pure Go/ASM implementation of CryptoNight hash function with its variants, without any CGO binding.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 84.5%
  • Assembly 15.5%