Repository: ferranbt/fastssz
Pull request #146 (2024-03-19 13:54:05)

chore(deps): Unfork `gohashtree`
@ferranbt prysm implemented the byte slice hasher you were maintaining a fork for.


Patch:
diff --git a/.gitignore b/.gitignore
index eed8efe..387c399 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,1 +1,2 @@
 eth2.0-spec-tests
+*.tar.gz
\ No newline at end of file
diff --git a/README.md b/README.md
index f2185bb..0cfec1b 100644
--- a/README.md
+++ b/README.md
@@ -103,6 +103,6 @@ There are some caveats required to use this functionality.
 
 ## Fast HashTreeRoot
 
-`Fastssz` integrates with Prysm [gohashtree](https://github.com/prysmaticlabs/gohashtree) library to do high performance and concurrent Sha256 hashing. It achieves a 2x performance improvement with respect to the normal sequential hashing. As of now, this feature is not yet enabled by default since it does not use the `gohashtree` main branch. Thus, a [fork](https://github.com/umbracle/gohashtree) of `gohashtree` with that branch is used. You can track the updates on [this](https://github.com/prysmaticlabs/gohashtree/issues/4) issue.
+`Fastssz` integrates with Prysm [gohashtree](github.com/prysmaticlabs/gohashtree) library to do high performance and concurrent Sha256 hashing. It achieves a 2x performance improvement with respect to the normal sequential hashing.
 
 In order to use this feature, enable manually the hash function in the Hasher like in the benchmark example.
diff --git a/go.mod b/go.mod
index f88deed..9ab5183 100644
--- a/go.mod
+++ b/go.mod
@@ -6,8 +6,8 @@ require (
 	github.com/golang/snappy v0.0.3
 	github.com/minio/sha256-simd v1.0.0
 	github.com/mitchellh/mapstructure v1.3.2
+	github.com/prysmaticlabs/gohashtree v0.0.4-beta
 	github.com/stretchr/testify v1.8.1
-	github.com/umbracle/gohashtree v0.0.2-alpha.0.20240116220325-8d974894cac9
 	gopkg.in/yaml.v2 v2.3.0
 )
 
diff --git a/go.sum b/go.sum
index b4f0e77..3411b81 100644
--- a/go.sum
+++ b/go.sum
@@ -12,6 +12,8 @@ github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYG
 github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4=
+github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -19,10 +21,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10 h1:CQh33pStIp/E30b7TxDlXfM0145bn2e8boI30IxAhTg=
-github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10/go.mod h1:x/Pa0FF5Te9kdrlZKJK82YmAkvL8+f989USgz6Jiw7M=
-github.com/umbracle/gohashtree v0.0.2-alpha.0.20240116220325-8d974894cac9 h1:ksdOx5rKt9I59ceXCNwf/Xa9JCPLPKtfbAf3qnTxUwE=
-github.com/umbracle/gohashtree v0.0.2-alpha.0.20240116220325-8d974894cac9/go.mod h1:x/Pa0FF5Te9kdrlZKJK82YmAkvL8+f989USgz6Jiw7M=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
diff --git a/hasher.go b/hasher.go
index 33d1bc3..ec3975d 100755
--- a/hasher.go
+++ b/hasher.go
@@ -341,7 +341,10 @@ func getDepth(d uint64) uint8 {
 }
 
 func (h *Hasher) merkleizeImpl(dst []byte, input []byte, limit uint64) []byte {
-	count := uint64(len(input) / 32)
+	// count is the number of 32 byte chunks from the input, after right-padding
+	// with zeroes to the next multiple of 32 bytes when the input is not aligned
+	// to a multiple of 32 bytes.
+	count := uint64((len(input) + 31) / 32)
 	if limit == 0 {
 		limit = count
 	} else if count > limit {


Test patch:
diff --git a/hasher_test.go b/hasher_test.go
index 1117f03..42ca70d 100755
--- a/hasher_test.go
+++ b/hasher_test.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/umbracle/gohashtree"
+	"github.com/prysmaticlabs/gohashtree"
 )
 
 func TestDepth(t *testing.T) {
@@ -68,7 +68,7 @@ func TestHashGoHashTree(t *testing.T) {
 	buf = append(buf, a...)
 	buf = append(buf, b...)
 
-	gohashtree.Hash(buf, buf)
+	gohashtree.HashByteSlice(buf, buf)
 
 	fmt.Println(buf)
 }
diff --git a/spectests/structs_test.go b/spectests/structs_test.go
index a1a7117..7e207f7 100644
--- a/spectests/structs_test.go
+++ b/spectests/structs_test.go
@@ -11,7 +11,7 @@ import (
 
 	ssz "github.com/ferranbt/fastssz"
 	"github.com/golang/snappy"
-	"github.com/umbracle/gohashtree"
+	"github.com/prysmaticlabs/gohashtree"
 
 	"gopkg.in/yaml.v2"
 )
@@ -205,7 +205,7 @@ func checkSSZEncoding(t *testing.T, fork fork, fileName, structName string, base
 	}
 
 	// Root with gohashtree
-	hh := ssz.NewHasherWithHashFn(gohashtree.Hash)
+	hh := ssz.NewHasherWithHashFn(gohashtree.HashByteSlice)
 	if err := obj.HashTreeRootWith(hh); err != nil {
 		fatal("GohashtreeRoot", err)
 	}
@@ -297,7 +297,7 @@ func BenchmarkHashTreeRoot_SuperFast(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	hh := ssz.NewHasherWithHashFn(gohashtree.Hash)
+	hh := ssz.NewHasherWithHashFn(gohashtree.HashByteSlice)
 	for i := 0; i < b.N; i++ {
 		obj.HashTreeRootWith(hh)
 		hh.Reset()
diff --git a/sszgen/testcases/container.go b/sszgen/testcases/container.go
new file mode 100644
index 0000000..4285c00
--- /dev/null
+++ b/sszgen/testcases/container.go
@@ -0,0 +1,7 @@
+package testcases
+
+//go:generate go run ../main.go --path container.go
+
+type Vec struct {
+	Values []uint64 `ssz-size:"6"`
+}
diff --git a/sszgen/testcases/container_encoding.go b/sszgen/testcases/container_encoding.go
new file mode 100644
index 0000000..166bb37
--- /dev/null
+++ b/sszgen/testcases/container_encoding.go
@@ -0,0 +1,83 @@
+// Code generated by fastssz. DO NOT EDIT.
+// Hash: acb511949371bd93802219589c0d97145e86ad6f3573e53f612cf206ac868df4
+// Version: 0.1.3
+package testcases
+
+import (
+	ssz "github.com/ferranbt/fastssz"
+)
+
+// MarshalSSZ ssz marshals the Vec object
+func (v *Vec) MarshalSSZ() ([]byte, error) {
+	return ssz.MarshalSSZ(v)
+}
+
+// MarshalSSZTo ssz marshals the Vec object to a target array
+func (v *Vec) MarshalSSZTo(buf []byte) (dst []byte, err error) {
+	dst = buf
+
+	// Field (0) 'Values'
+	if size := len(v.Values); size != 6 {
+		err = ssz.ErrVectorLengthFn("Vec.Values", size, 6)
+		return
+	}
+	for ii := 0; ii < 6; ii++ {
+		dst = ssz.MarshalUint64(dst, v.Values[ii])
+	}
+
+	return
+}
+
+// UnmarshalSSZ ssz unmarshals the Vec object
+func (v *Vec) UnmarshalSSZ(buf []byte) error {
+	var err error
+	size := uint64(len(buf))
+	if size != 48 {
+		return ssz.ErrSize
+	}
+
+	// Field (0) 'Values'
+	v.Values = ssz.ExtendUint64(v.Values, 6)
+	for ii := 0; ii < 6; ii++ {
+		v.Values[ii] = ssz.UnmarshallUint64(buf[0:48][ii*8 : (ii+1)*8])
+	}
+
+	return err
+}
+
+// SizeSSZ returns the ssz encoded size in bytes for the Vec object
+func (v *Vec) SizeSSZ() (size int) {
+	size = 48
+	return
+}
+
+// HashTreeRoot ssz hashes the Vec object
+func (v *Vec) HashTreeRoot() ([32]byte, error) {
+	return ssz.HashWithDefaultHasher(v)
+}
+
+// HashTreeRootWith ssz hashes the Vec object with a hasher
+func (v *Vec) HashTreeRootWith(hh ssz.HashWalker) (err error) {
+	indx := hh.Index()
+
+	// Field (0) 'Values'
+	{
+		if size := len(v.Values); size != 6 {
+			err = ssz.ErrVectorLengthFn("Vec.Values", size, 6)
+			return
+		}
+		subIndx := hh.Index()
+		for _, i := range v.Values {
+			hh.AppendUint64(i)
+		}
+		hh.Merkleize(subIndx)
+	}
+
+	hh.Merkleize(indx)
+	return
+}
+
+// GetTree ssz hashes the Vec object
+func (v *Vec) GetTree() (*ssz.Node, error) {
+	return ssz.ProofTree(v)
+}
diff --git a/sszgen/testcases/container_test.go b/sszgen/testcases/container_test.go
new file mode 100644
index 0000000..7201d87
--- /dev/null
+++ b/sszgen/testcases/container_test.go
@@ -0,0 +1,25 @@
+package testcases
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestVectorContainer(t *testing.T) {
+	v := &Vec{
+		Values: []uint64{1, 2, 3, 4, 5, 6},
+	}
+	expectedHash := [32]byte{
+		0xac, 0x13, 0x6e, 0xdd, 0xa3, 0xbd, 0xd2, 0xe9,
+		0x49, 0xa1, 0x9a, 0x94, 0x5b, 0x1a, 0xc5, 0x54,
+		0xe4, 0xb6, 0x07, 0xd3, 0x39, 0xa4, 0x3c, 0x54,
+		0x0c, 0x33, 0x60, 0x98, 0xff, 0xf9, 0x7f, 0x2b,
+	}
+	h, err := v.HashTreeRoot()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !bytes.Equal(h[:], expectedHash[:]) {
+		t.Fatalf("hash mismatch")
+	}
+}