Skip to content

Commit

Permalink
Minor NITs throughout
Browse files Browse the repository at this point in the history
  • Loading branch information
Olshansk committed May 28, 2024
1 parent 2dc7014 commit e408436
Show file tree
Hide file tree
Showing 12 changed files with 229 additions and 153 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Benchmarking

cpu.prof
mem.prof
ring-go.test
59 changes: 59 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.SILENT:

#####################
### General ###
#####################

.PHONY: help
.DEFAULT_GOAL := help
help: ## Prints all the targets in all the Makefiles
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: list
list: ## List all make targets
@${MAKE} -pRrn : -f $(MAKEFILE_LIST) 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | sort

#####################
#### Testing ####
#####################

.PHONY: test_all
test_all: ## runs the test suite
go test -v -p 1 ./... -mod=readonly -race

##########################
#### Benchmarking ####
##########################

.PHONY: benchmark_all
benchmark_all: ## runs the benchmark suite
go test -bench=. -benchmem -cpuprofile=cpu.prof -memprofile=mem.prof

###########################
### Release Helpers ###
###########################

# List tags: git tag
# Delete tag locally: git tag -d v1.2.3
# Delete tag remotely: git push --delete origin v1.2.3

.PHONY: tag_bug_fix
tag_bug_fix: ## Tag a new bug fix release (e.g., v1.0.1 -> v1.0.2)
@$(eval LATEST_TAG=$(shell git tag --sort=-v:refname | head -n 1))
@$(eval NEW_TAG=$(shell echo $(LATEST_TAG) | awk -F. -v OFS=. '{ $$NF = sprintf("%d", $$NF + 1); print }'))
@git tag $(NEW_TAG)
@echo "New bug fix version tagged: $(NEW_TAG)"
@echo "Run the following commands to push the new tag:"
@echo " git push origin $(NEW_TAG)"
@echo "And draft a new release at https://github.com/pokt-network/smt/releases/new"


.PHONY: tag_minor_release
tag_minor_release: ## Tag a new minor release (e.g. v1.0.0 -> v1.1.0)
@$(eval LATEST_TAG=$(shell git tag --sort=-v:refname | head -n 1))
@$(eval NEW_TAG=$(shell echo $(LATEST_TAG) | awk -F. '{$$2 += 1; $$3 = 0; print $$1 "." $$2 "." $$3}'))
@git tag $(NEW_TAG)
@echo "New minor release version tagged: $(NEW_TAG)"
@echo "Run the following commands to push the new tag:"
@echo " git push origin $(NEW_TAG)"
@echo "And draft a new release at https://github.com/pokt-network/smt/releases/new"
74 changes: 40 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,72 @@
# ring-go
# ring-go <!-- omit in toc -->

Implementation of linkable ring signatures using elliptic curve crypto in pure Go. It supports ring signatures over both ed25519 and secp256k1.
Implementation of linkable ring signatures using elliptic curve crypto in pure Go.
It supports ring signatures over both ed25519 and secp256k1.

### requirements
- [Requirements](#requirements)
- [Install](#install)
- [References](#references)
- [Usage](#usage)

go 1.19
## Requirements

### get
go 1.22.2

## Install

`go get github.com/pokt-network/ring-go`

### references
## References

This implementation is based off of [Ring Confidential Transactions](https://eprint.iacr.org/2015/1098.pdf), in particular section 2, which defines MLSAG (Multilayered Linkable Spontaneous Anonymous Group signatures).

### usage
## Usage

See `examples/main.go`.

```go
package main

import (
"fmt"
"fmt"

ring "github.com/pokt-network/ring-go"
"golang.org/x/crypto/sha3"
ring "github.com/pokt-network/ring-go"
"golang.org/x/crypto/sha3"
)

func signAndVerify(curve ring.Curve) {
privkey := curve.NewRandomScalar()
msgHash := sha3.Sum256([]byte("helloworld"))
privKey := curve.NewRandomScalar()
msgHash := sha3.Sum256([]byte("helloworld"))

// size of the public key ring (anonymity set)
const size = 16
// size of the public key ring (anonymity set)
const size = 16

// our key's secret index within the set
const idx = 7
// our key's secret index within the set
const idx = 7

keyring, err := ring.NewKeyRing(curve, size, privkey, idx)
if err != nil {
panic(err)
}
keyring, err := ring.NewKeyRing(curve, size, privKey, idx)
if err != nil {
panic(err)
}

sig, err := keyring.Sign(msgHash, privkey)
if err != nil {
panic(err)
}
sig, err := keyring.Sign(msgHash, privKey)
if err != nil {
panic(err)
}

ok := sig.Verify(msgHash)
if !ok {
fmt.Println("failed to verify :(")
return
}
ok := sig.Verify(msgHash)
if !ok {
fmt.Println("failed to verify :(")
return
}

fmt.Println("verified signature!")
fmt.Println("verified signature!")
}

func main() {
fmt.Println("using secp256k1...")
signAndVerify(ring.Secp256k1())
fmt.Println("using ed25519...")
signAndVerify(ring.Ed25519())
fmt.Println("using secp256k1...")
signAndVerify(ring.Secp256k1())
fmt.Println("using ed25519...")
signAndVerify(ring.Ed25519())
}
```
98 changes: 49 additions & 49 deletions bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import (

const idx = 0

func benchmarkSign(b *testing.B, curve types.Curve, keyring *Ring, privkey types.Scalar, size, idx int) {
func benchmarkSign(b *testing.B, curve types.Curve, keyring *Ring, privKey types.Scalar, size, idx int) {
for i := 0; i < b.N; i++ {
_, err := keyring.Sign(testMsg, privkey)
_, err := keyring.Sign(testMsg, privKey)
if err != nil {
panic(err)
}
}
}

func mustKeyRing(curve types.Curve, privkey types.Scalar, size, idx int) *Ring {
keyring, err := NewKeyRing(curve, size, privkey, idx)
func mustKeyRing(curve types.Curve, privKey types.Scalar, size, idx int) *Ring {
keyring, err := NewKeyRing(curve, size, privKey, idx)
if err != nil {
panic(err)
}
Expand All @@ -28,113 +28,113 @@ func mustKeyRing(curve types.Curve, privkey types.Scalar, size, idx int) *Ring {
func BenchmarkSign2_Secp256k1(b *testing.B) {
const size = 2
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign4_Secp256k1(b *testing.B) {
const size = 4
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign8_Secp256k1(b *testing.B) {
const size = 8
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign16_Secp256k1(b *testing.B) {
const size = 16
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign32_Secp256k1(b *testing.B) {
const size = 2
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign64_Secp256k1(b *testing.B) {
const size = 64
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign128_Secp256k1(b *testing.B) {
const size = 128
curve := Secp256k1()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign2_Ed25519(b *testing.B) {
const size = 2
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign4_Ed25519(b *testing.B) {
const size = 4
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign8_Ed25519(b *testing.B) {
const size = 8
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign16_Ed25519(b *testing.B) {
const size = 16
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign32_Ed25519(b *testing.B) {
const size = 32
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign64_Ed25519(b *testing.B) {
const size = 64
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func BenchmarkSign128_Ed25519(b *testing.B) {
const size = 128
curve := Ed25519()
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
benchmarkSign(b, curve, keyring, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)
benchmarkSign(b, curve, keyring, privKey, size, idx)
}

func benchmarkVerify(b *testing.B, sig *RingSig) {
Expand All @@ -147,10 +147,10 @@ func benchmarkVerify(b *testing.B, sig *RingSig) {
}

func mustSig(curve types.Curve, size int) *RingSig {
privkey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privkey, size, idx)
privKey := curve.NewRandomScalar()
keyring := mustKeyRing(curve, privKey, size, idx)

sig, err := keyring.Sign(testMsg, privkey)
sig, err := keyring.Sign(testMsg, privKey)
if err != nil {
panic(err)
}
Expand Down
15 changes: 10 additions & 5 deletions benchmarks.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
# Benchmarks

The current library benchmarks for signing and verification are located below. For ring signatures, the signing and verification time are linearly proportional to the number of members of the ring (or "anonymity set"), which is what's observed.
The current library benchmarks for signing and verification are located below.
For ring signatures, the signing and verification time are linearly proportional
to the number of members of the ring (or "anonymity set"), which is what's observed.

> Note: the number directly after `BenchmarkSign` or `BenchmarkVerify` in the test name is the ring size being benchmarked.
> Note: the number directly after `BenchmarkSign` or `BenchmarkVerify` in the test
> name is the ring size being benchmarked.
> Note: the ns/op value on the right is the time it took for signing or verification (depending on the test). The middle value is the number of times the operation was executed by the Go benchmarker.
> Note: the ns/op value on the right is the time it took for signing or verification
> (depending on the test). The middle value is the number of times the operation
> was executed by the Go benchmarker.
Summary:
**Summary:**

- secp256k1 signing and verification is around 0.92ms per ring member
- ed25519 signing and verification is around is around 0.42ms per ring member

```
```bash
goos: linux
goarch: amd64
pkg: github.com/pokt-network/ring-go
Expand Down
Loading

0 comments on commit e408436

Please sign in to comment.