Skip to content

Commit

Permalink
Merge pull request txaty#1 from elliotwutingfeng/main
Browse files Browse the repository at this point in the history
1. Add helper Makefile for running tests/benchmarks,
2. Increase test coverage,
3. Bump GitHub Actions versions.
  • Loading branch information
txaty authored Aug 13, 2022
2 parents 236cf65 + 1ca72e6 commit e39c9c5
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 92 deletions.
19 changes: 9 additions & 10 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version-file: './go.mod'

- name: Build
run: go build -v ./...
run: make build

- name: Test
run: go test -v ./...
run: make tests_race

- name: Run golangci-lint
# You may pin to the exact commit or the version.
Expand All @@ -34,17 +34,17 @@ jobs:
name: Update coverage badge
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.

- name: Setup go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: '1.14.4'
go-version-file: './go.mod'

- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
Expand All @@ -53,16 +53,15 @@ jobs:
- name: Run Test
run: |
go test -v ./... -covermode=count -coverprofile=coverage.out
go tool cover -func=coverage.out -o=coverage.out
make tests_race
- name: Go Coverage Badge # Pass the `coverage.out` output to this action
uses: tj-actions/[email protected]
with:
filename: coverage.out

- name: Verify Changed files
uses: tj-actions/verify-changed-files@v9.1
uses: tj-actions/verify-changed-files@v10.1
id: verify-changed-files
with:
files: README.md
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.prof

# Binaries for programs and plugins
*.exe
*.exe~
Expand All @@ -10,6 +12,7 @@

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.html

# Dependency directories (remove the comment below to include it)
vendor/
Expand Down
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
tests:
go test -v -covermode count -coverprofile coverage.out && go tool cover -html coverage.out -o coverage.html && go tool cover -func coverage.out -o coverage.out

tests_race:
go test -v -race -covermode atomic -coverprofile coverage.out && go tool cover -html coverage.out -o coverage.html && go tool cover -func coverage.out -o coverage.out

format:
go fmt .

bench:
go test -bench . -benchmem -cpu 1

report_bench:
go test -cpuprofile cpu.prof -memprofile mem.prof -bench . -cpu 1

cpu_report:
go tool pprof cpu.prof

mem_report:
go tool pprof mem.prof

build:
go build -v ./...
162 changes: 80 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Go Reference](https://pkg.go.dev/badge/github.com/txaty/go-merkletree.svg)](https://pkg.go.dev/github.com/txaty/go-merkletree)
[![Go Report Card](https://goreportcard.com/badge/github.com/txaty/go-merkletree)](https://goreportcard.com/report/github.com/txaty/go-merkletree)
![Coverage](https://img.shields.io/badge/Coverage-87.2%25-brightgreen)
![Coverage](https://img.shields.io/badge/Coverage-87.8%25-brightgreen)

High performance Merkle Tree Computation in Go (supports parallelization).

Expand All @@ -12,80 +12,79 @@ High performance Merkle Tree Computation in Go (supports parallelization).
go get -u github.com/txaty/go-merkletree
```


## Example

```go
package main

import (
"crypto/rand"
"crypto/sha256"
"fmt"
"crypto/rand"
"crypto/sha256"
"fmt"

mt "github.com/txaty/go-merkletree"
mt "github.com/txaty/go-merkletree"
)

// first define a data structure with Serialize method to be used as data block
type testData struct {
data []byte
data []byte
}

func (t *testData) Serialize() ([]byte, error) {
return t.data, nil
return t.data, nil
}

// define a hash function in this format
func hashFunc(data []byte) ([]byte, error) {
sha256Func := sha256.New()
sha256Func.Write(data)
return sha256Func.Sum(nil), nil
sha256Func := sha256.New()
sha256Func.Write(data)
return sha256Func.Sum(nil), nil
}

func main() {
// generate dummy data blocks
var blocks []mt.DataBlock
for i := 0; i < 1000; i++ {
block := &testData{
data: make([]byte, 100),
}
_, err := rand.Read(block.data)
handleError(err)
blocks = append(blocks, block)
}

// create a simple configuration for Merkle Tree generation
config := &mt.Config{
HashFunc: hashFunc, // if nil, use SHA256 by default
// if true, handle odd-number-node situation by duplicating the last node
AllowDuplicates: true,
}
// build a new Merkle Tree
tree, err := mt.New(blocks, config)
handleError(err)
// get the root hash of the Merkle Tree
rootHash := tree.Root
// get proves
proofs := tree.Proofs
// verify the proofs
for i := 0; i < len(proofs); i++ {
ok, err := tree.Verify(blocks[i], proofs[i])
handleError(err)
fmt.Println(ok)
}
// or you can also do this
for i := 0; i < len(blocks); i++ {
// if hashFunc is nil, use SHA256 by default
ok, err := mt.Verify(blocks[i], proofs[i], rootHash, hashFunc)
handleError(err)
fmt.Println(ok)
}
// generate dummy data blocks
var blocks []mt.DataBlock
for i := 0; i < 1000; i++ {
block := &testData{
data: make([]byte, 100),
}
_, err := rand.Read(block.data)
handleError(err)
blocks = append(blocks, block)
}

// create a simple configuration for Merkle Tree generation
config := &mt.Config{
HashFunc: hashFunc, // if nil, use SHA256 by default
// if true, handle odd-number-node situation by duplicating the last node
AllowDuplicates: true,
}
// build a new Merkle Tree
tree, err := mt.New(blocks, config)
handleError(err)
// get the root hash of the Merkle Tree
rootHash := tree.Root
// get proves
proofs := tree.Proofs
// verify the proofs
for i := 0; i < len(proofs); i++ {
ok, err := tree.Verify(blocks[i], proofs[i])
handleError(err)
fmt.Println(ok)
}
// or you can also do this
for i := 0; i < len(blocks); i++ {
// if hashFunc is nil, use SHA256 by default
ok, err := mt.Verify(blocks[i], proofs[i], rootHash, hashFunc)
handleError(err)
fmt.Println(ok)
}
}

func handleError(err error) {
if err != nil {
panic(err)
}
if err != nil {
panic(err)
}
}
```

Expand All @@ -108,15 +107,15 @@ goarch: amd64
pkg: github.com/txaty/go-merkletree
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkMerkleTreeBuild
BenchmarkMerkleTreeBuild-12 523 2221038 ns/op
BenchmarkMerkleTreeBuild-12 523 2221038 ns/op
BenchmarkMerkleTreeBuildParallel
BenchmarkMerkleTreeBuildParallel-12 678 1758174 ns/op
BenchmarkMerkleTreeBuildParallel-12 678 1758174 ns/op
Benchmark_cbergoonMerkleTreeBuild
Benchmark_cbergoonMerkleTreeBuild-12 164 7193082 ns/op
Benchmark_cbergoonMerkleTreeBuild-12 164 7193082 ns/op
BenchmarkMerkleTreeVerify
BenchmarkMerkleTreeVerify-12 176 6787151 ns/op
BenchmarkMerkleTreeVerify-12 176 6787151 ns/op
Benchmark_cbergoonMerkleTreeVerify
Benchmark_cbergoonMerkleTreeVerify-12 48 24503759 ns/op
Benchmark_cbergoonMerkleTreeVerify-12 48 24503759 ns/op
PASS
```

Expand All @@ -127,15 +126,15 @@ goos: darwin
goarch: arm64
pkg: github.com/txaty/go-merkletree
BenchmarkMerkleTreeBuild
BenchmarkMerkleTreeBuild-8 1926 621450 ns/op
BenchmarkMerkleTreeBuild-8 1926 621450 ns/op
BenchmarkMerkleTreeBuildParallel
BenchmarkMerkleTreeBuildParallel-8 1980 597595 ns/op
BenchmarkMerkleTreeBuildParallel-8 1980 597595 ns/op
Benchmark_cbergoonMerkleTreeBuild
Benchmark_cbergoonMerkleTreeBuild-8 416 2873425 ns/op
Benchmark_cbergoonMerkleTreeBuild-8 416 2873425 ns/op
BenchmarkMerkleTreeVerify
BenchmarkMerkleTreeVerify-8 1024 1162340 ns/op
BenchmarkMerkleTreeVerify-8 1024 1162340 ns/op
Benchmark_cbergoonMerkleTreeVerify
Benchmark_cbergoonMerkleTreeVerify-8 198 6064883 ns/op
Benchmark_cbergoonMerkleTreeVerify-8 198 6064883 ns/op
PASS
```

Expand All @@ -155,15 +154,15 @@ goarch: amd64
pkg: github.com/txaty/go-merkletree
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkMerkleTreeBuild
BenchmarkMerkleTreeBuild-12 44 26247088 ns/op
BenchmarkMerkleTreeBuild-12 44 26247088 ns/op
BenchmarkMerkleTreeBuildParallel
BenchmarkMerkleTreeBuildParallel-12 88 13200423 ns/op
BenchmarkMerkleTreeBuildParallel-12 88 13200423 ns/op
Benchmark_cbergoonMerkleTreeBuild
Benchmark_cbergoonMerkleTreeBuild-12 2 522912836 ns/op
Benchmark_cbergoonMerkleTreeBuild-12 2 522912836 ns/op
BenchmarkMerkleTreeVerify
BenchmarkMerkleTreeVerify-12 12 92832728 ns/op
BenchmarkMerkleTreeVerify-12 12 92832728 ns/op
Benchmark_cbergoonMerkleTreeVerify
Benchmark_cbergoonMerkleTreeVerify-12 2 775982655 ns/op
Benchmark_cbergoonMerkleTreeVerify-12 2 775982655 ns/op
PASS
```

Expand All @@ -174,15 +173,15 @@ goos: darwin
goarch: arm64
pkg: github.com/txaty/go-merkletree
BenchmarkMerkleTreeBuild
BenchmarkMerkleTreeBuild-8 150 7583059 ns/op
BenchmarkMerkleTreeBuild-8 150 7583059 ns/op
BenchmarkMerkleTreeBuildParallel
BenchmarkMerkleTreeBuildParallel-8 193 6213593 ns/op
BenchmarkMerkleTreeBuildParallel-8 193 6213593 ns/op
Benchmark_cbergoonMerkleTreeBuild
Benchmark_cbergoonMerkleTreeBuild-8 5 231274467 ns/op
Benchmark_cbergoonMerkleTreeBuild-8 5 231274467 ns/op
BenchmarkMerkleTreeVerify
BenchmarkMerkleTreeVerify-8 72 16243839 ns/op
BenchmarkMerkleTreeVerify-8 72 16243839 ns/op
Benchmark_cbergoonMerkleTreeVerify
Benchmark_cbergoonMerkleTreeVerify-8 4 282454323 ns/op
Benchmark_cbergoonMerkleTreeVerify-8 4 282454323 ns/op
PASS
```

Expand All @@ -202,15 +201,15 @@ goarch: amd64
pkg: github.com/txaty/go-merkletree
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkMerkleTreeBuild
BenchmarkMerkleTreeBuild-12 4 314272598 ns/op
BenchmarkMerkleTreeBuild-12 4 314272598 ns/op
BenchmarkMerkleTreeBuildParallel
BenchmarkMerkleTreeBuildParallel-12 7 144025900 ns/op
BenchmarkMerkleTreeBuildParallel-12 7 144025900 ns/op
Benchmark_cbergoonMerkleTreeBuild
Benchmark_cbergoonMerkleTreeBuild-12 1 59839840747 ns/op
Benchmark_cbergoonMerkleTreeBuild-12 1 59839840747 ns/op
BenchmarkMerkleTreeVerify
BenchmarkMerkleTreeVerify-12 1 1128593176 ns/op
BenchmarkMerkleTreeVerify-12 1 1128593176 ns/op
Benchmark_cbergoonMerkleTreeVerify
Benchmark_cbergoonMerkleTreeVerify-12 1 63145758422 ns/op
Benchmark_cbergoonMerkleTreeVerify-12 1 63145758422 ns/op
PASS
```

Expand All @@ -221,15 +220,15 @@ goos: darwin
goarch: arm64
pkg: github.com/txaty/go-merkletree
BenchmarkMerkleTreeBuild
BenchmarkMerkleTreeBuild-8 12 99413837 ns/op
BenchmarkMerkleTreeBuild-8 12 99413837 ns/op
BenchmarkMerkleTreeBuildParallel
BenchmarkMerkleTreeBuildParallel-8 14 77042113 ns/op
BenchmarkMerkleTreeBuildParallel-8 14 77042113 ns/op
Benchmark_cbergoonMerkleTreeBuild
Benchmark_cbergoonMerkleTreeBuild-8 1 29609023292 ns/op
Benchmark_cbergoonMerkleTreeBuild-8 1 29609023292 ns/op
BenchmarkMerkleTreeVerify
BenchmarkMerkleTreeVerify-8 6 193811917 ns/op
BenchmarkMerkleTreeVerify-8 6 193811917 ns/op
Benchmark_cbergoonMerkleTreeVerify
Benchmark_cbergoonMerkleTreeVerify-8 1 30393054541 ns/op
Benchmark_cbergoonMerkleTreeVerify-8 1 30393054541 ns/op
PASS
```

Expand All @@ -239,4 +238,3 @@ PASS
(```63145758422 ns/op``` means each function execution takes 63145758422 nanoseconds (around 63.15 seconds, 10^9 ns = 1s))

In conclusion, with large sets of data blocks, our implementation is much faster than cbergoon/merkletree at both tree & proof generation and data block verification.

13 changes: 13 additions & 0 deletions merkle_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ func TestMerkleTree_Verify(t *testing.T) {
}
}

func TestVerify(t *testing.T) {
m, blocks, _ := verifySetup(2)
// hashFunc is nil
got, err := Verify(blocks[0], m.Proofs[0], []byte{}, nil)
if err != nil {
t.Errorf("Verify() error = %v, wantErr %v", err, nil)
return
}
if got {
t.Errorf("Verify() got = %v, want %v", got, false)
}
}

func BenchmarkMerkleTreeNew(b *testing.B) {
config := &Config{
HashFunc: defaultHashFunc,
Expand Down

0 comments on commit e39c9c5

Please sign in to comment.