support semantic hashing list

This commit is contained in:
Jürgen Gamenik 2025-08-01 16:40:56 +02:00
parent 32d537cd58
commit 4dda77c540
6 changed files with 76 additions and 23 deletions

View file

@ -1675,6 +1675,35 @@ func TestAdd(t *testing.T) {
} }
} }
func TestCommitmentList(t *testing.T) {
var liste []kzg4844.Commitment
for i := 0; i < 4; i++ {
blob := &kzg4844.Blob{byte(i)}
commit, _ := kzg4844.BlobToCommitment(blob)
liste = append(liste, commit)
}
output := make([]common.Hash, 4)
kzg4844.CalcBlobHashListV1(liste, output)
if output[0][0] != 1 || output[0][1] != 6 ||
output[0][30] != 64 || output[0][31] != 20 {
t.Errorf("Hash 1 is different")
}
if output[1][0] != 1 || output[1][1] != 90 ||
output[1][30] != 47 || output[1][31] != 104 {
t.Errorf("Hash 2 is different")
}
if output[2][0] != 1 || output[2][1] != 129 ||
output[2][30] != 50 || output[2][31] != 12 {
t.Errorf("Hash 3 is different")
}
if output[3][0] != 1 || output[3][1] != 53 ||
output[3][30] != 101 || output[3][31] != 224 {
t.Errorf("Hash 4 is different")
}
}
// fakeBilly is a billy.Database implementation which just drops data on the floor. // fakeBilly is a billy.Database implementation which just drops data on the floor.
type fakeBilly struct { type fakeBilly struct {
billy.Database billy.Database

View file

@ -18,7 +18,6 @@ package types
import ( import (
"bytes" "bytes"
"crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@ -87,11 +86,8 @@ func NewBlobTxSidecar(version byte, blobs []kzg4844.Blob, commitments []kzg4844.
// BlobHashes computes the blob hashes of the given blobs. // BlobHashes computes the blob hashes of the given blobs.
func (sc *BlobTxSidecar) BlobHashes() []common.Hash { func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
hasher := sha256.New()
h := make([]common.Hash, len(sc.Commitments)) h := make([]common.Hash, len(sc.Commitments))
for i := range sc.Blobs { kzg4844.CalcBlobHashListV1(sc.Commitments, h)
h[i] = kzg4844.CalcBlobHashV1(hasher, &sc.Commitments[i])
}
return h return h
} }
@ -153,11 +149,11 @@ func (sc *BlobTxSidecar) ValidateBlobCommitmentHashes(hashes []common.Hash) erro
if len(sc.Commitments) != len(hashes) { if len(sc.Commitments) != len(hashes) {
return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(sc.Commitments), len(hashes)) return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(sc.Commitments), len(hashes))
} }
hasher := sha256.New() var listComputed = make([]common.Hash, len(hashes))
kzg4844.CalcBlobHashListV1(sc.Commitments, listComputed)
for i, vhash := range hashes { for i, vhash := range hashes {
computed := kzg4844.CalcBlobHashV1(hasher, &sc.Commitments[i]) if vhash != listComputed[i] {
if vhash != computed { return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, listComputed[i], vhash)
return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, computed, vhash)
} }
} }
return nil return nil

View file

@ -18,12 +18,15 @@
package kzg4844 package kzg4844
import ( import (
"crypto/sha256"
"embed" "embed"
"errors" "errors"
"hash" "hash"
"reflect" "reflect"
"sync"
"sync/atomic" "sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
) )
@ -185,6 +188,39 @@ func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) {
return vh return vh
} }
// CalcBlobHashListV1 calculates the 'versioned blob hash' of a list of commitment with 2 go routines.
func CalcBlobHashListV1(list []Commitment, output []common.Hash) {
if len(list) != len(output) {
panic("wrong output size")
}
if len(list) == 0 {
return
}
hasher1 := sha256.New()
if len(list) == 1 {
output[0] = CalcBlobHashV1(hasher1, &list[0])
return
}
var wg sync.WaitGroup
wg.Add(2)
go calcBlobHashListPartV1(list, output, &wg, hasher1, 0)
hasher2 := sha256.New()
go calcBlobHashListPartV1(list, output, &wg, hasher2, 1)
wg.Wait()
}
// calcs hashes of all odd or all even parts of the list
func calcBlobHashListPartV1(list []Commitment, output []common.Hash, wg *sync.WaitGroup, hasher hash.Hash, where int) {
defer wg.Done()
for ; where < len(list); where += 2 {
hasher.Reset()
var commitment *Commitment = &list[where]
hasher.Write(commitment[:])
hasher.Sum(output[where][:0])
output[where][0] = 0x01 // version
}
}
// IsValidVersionedHash checks that h is a structurally-valid versioned blob hash. // IsValidVersionedHash checks that h is a structurally-valid versioned blob hash.
func IsValidVersionedHash(h []byte) bool { func IsValidVersionedHash(h []byte) bool {
return len(h) == 32 && h[0] == 0x01 return len(h) == 32 && h[0] == 0x01

View file

@ -18,7 +18,6 @@
package catalyst package catalyst
import ( import (
"crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"strconv" "strconv"
@ -496,7 +495,6 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo
} }
var ( var (
res = make([]*engine.BlobAndProofV1, len(hashes)) res = make([]*engine.BlobAndProofV1, len(hashes))
hasher = sha256.New()
index = make(map[common.Hash]int) index = make(map[common.Hash]int)
sidecars = api.eth.BlobTxPool().GetBlobs(hashes) sidecars = api.eth.BlobTxPool().GetBlobs(hashes)
) )
@ -509,8 +507,10 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo
// already filled // already filled
continue continue
} }
for cIdx, commitment := range sidecar.Commitments { var listComputed = make([]common.Hash, len(sidecar.Commitments))
computed := kzg4844.CalcBlobHashV1(hasher, &commitment) kzg4844.CalcBlobHashListV1(sidecar.Commitments, listComputed)
for cIdx, _ := range sidecar.Commitments {
computed := listComputed[cIdx]
if idx, ok := index[computed]; ok { if idx, ok := index[computed]; ok {
res[idx] = &engine.BlobAndProofV1{ res[idx] = &engine.BlobAndProofV1{
Blob: sidecar.Blobs[cIdx][:], Blob: sidecar.Blobs[cIdx][:],

View file

@ -19,7 +19,6 @@ package ethapi
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"math" "math"
@ -341,10 +340,7 @@ func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context) error {
} }
hashes := make([]common.Hash, n) hashes := make([]common.Hash, n)
hasher := sha256.New() kzg4844.CalcBlobHashListV1(args.Commitments, hashes)
for i, c := range args.Commitments {
hashes[i] = kzg4844.CalcBlobHashV1(hasher, &c)
}
if args.BlobHashes != nil { if args.BlobHashes != nil {
for i, h := range hashes { for i, h := range hashes {
if h != args.BlobHashes[i] { if h != args.BlobHashes[i] {

View file

@ -18,7 +18,6 @@ package apitypes
import ( import (
"bytes" "bytes"
"crypto/sha256"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -266,10 +265,7 @@ func (args *SendTxArgs) validateTxSidecar() error {
} }
hashes := make([]common.Hash, n) hashes := make([]common.Hash, n)
hasher := sha256.New() kzg4844.CalcBlobHashListV1(args.Commitments, hashes)
for i, c := range args.Commitments {
hashes[i] = kzg4844.CalcBlobHashV1(hasher, &c)
}
if args.BlobHashes != nil { if args.BlobHashes != nil {
for i, h := range hashes { for i, h := range hashes {
if h != args.BlobHashes[i] { if h != args.BlobHashes[i] {