Skip to content

Commit fce14ba

Browse files
authored
Efficient Fiat-Shamir challenges using hashing (#15)
By avoiding ssz merklelization, we significantly reduce the latency of generating FS challenges. Before: ``` BenchmarkVerifyMultiple/8-6 16 69890960 ns/op 25221325 B/op 399904 allocs/op BenchmarkVerifyMultiple/16-6 8 138506286 ns/op 50439658 B/op 799792 allocs/op ``` After: ``` BenchmarkVerifyMultiple/8-6 27 41349482 ns/op 22059083 B/op 301451 allocs/op BenchmarkVerifyMultiple/16-6 14 80868200 ns/op 44114668 B/op 602909 allocs/op ```
1 parent df336b7 commit fce14ba

File tree

2 files changed

+56
-12
lines changed

2 files changed

+56
-12
lines changed

core/types/data_blob.go

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,12 @@ func (blobs Blobs) ComputeCommitmentsAndAggregatedProof() (commitments []KZGComm
377377
for i := range aggregatePoly {
378378
aggregateBlob[i] = bls.FrTo32(&aggregatePoly[i])
379379
}
380-
root := tree.GetHashFn().HashTreeRoot(&aggregateBlob, &aggregateCommitment)
380+
sum, err := sszHash(&PolynomialAndCommitment{aggregateBlob, aggregateCommitment})
381+
if err != nil {
382+
return nil, nil, KZGProof{}, err
383+
}
381384
var z bls.Fr
382-
hashToFr(&z, root)
385+
hashToFr(&z, sum)
383386

384387
var y bls.Fr
385388
kzg.EvaluatePolyInEvaluationForm(&y, aggregatePoly[:], &z)
@@ -399,8 +402,20 @@ type BlobsAndCommitments struct {
399402
BlobKzgs BlobKzgs
400403
}
401404

402-
func (h *BlobsAndCommitments) HashTreeRoot(hFn tree.HashFn) tree.Root {
403-
return hFn.HashTreeRoot(&h.Blobs, &h.BlobKzgs)
405+
func (b *BlobsAndCommitments) HashTreeRoot(hFn tree.HashFn) tree.Root {
406+
return hFn.HashTreeRoot(&b.Blobs, &b.BlobKzgs)
407+
}
408+
409+
func (b *BlobsAndCommitments) Serialize(w *codec.EncodingWriter) error {
410+
return w.Container(&b.Blobs, &b.BlobKzgs)
411+
}
412+
413+
func (b *BlobsAndCommitments) ByteLength() uint64 {
414+
return codec.ContainerLength(&b.Blobs, &b.BlobKzgs)
415+
}
416+
417+
func (b *BlobsAndCommitments) FixedLength() uint64 {
418+
return 0
404419
}
405420

406421
type PolynomialAndCommitment struct {
@@ -412,6 +427,18 @@ func (p *PolynomialAndCommitment) HashTreeRoot(hFn tree.HashFn) tree.Root {
412427
return hFn.HashTreeRoot(&p.b, &p.c)
413428
}
414429

430+
func (p *PolynomialAndCommitment) Serialize(w *codec.EncodingWriter) error {
431+
return w.Container(&p.b, &p.c)
432+
}
433+
434+
func (p *PolynomialAndCommitment) ByteLength() uint64 {
435+
return codec.ContainerLength(&p.b, &p.c)
436+
}
437+
438+
func (p *PolynomialAndCommitment) FixedLength() uint64 {
439+
return 0
440+
}
441+
415442
type BlobTxWrapper struct {
416443
Tx SignedBlobTx
417444
BlobKzgs BlobKzgs
@@ -487,10 +514,12 @@ func (b *BlobTxWrapData) verifyBlobs(inner TxData) error {
487514
}
488515
var aggregateCommitment KZGCommitment
489516
copy(aggregateCommitment[:], bls.ToCompressedG1(aggregateCommitmentG1))
490-
hasher := PolynomialAndCommitment{aggregateBlob, aggregateCommitment}
491-
root := hasher.HashTreeRoot(tree.GetHashFn())
517+
sum, err := sszHash(&PolynomialAndCommitment{aggregateBlob, aggregateCommitment})
518+
if err != nil {
519+
return err
520+
}
492521
var z bls.Fr
493-
hashToFr(&z, root)
522+
hashToFr(&z, sum)
494523

495524
var y bls.Fr
496525
kzg.EvaluatePolyInEvaluationForm(&y, aggregatePoly[:], &z)
@@ -555,10 +584,12 @@ func computePowers(r *bls.Fr, n int) []bls.Fr {
555584

556585
func computeAggregateKzgCommitment(blobs Blobs, commitments []KZGCommitment) ([]bls.Fr, *bls.G1Point, error) {
557586
// create challenges
558-
hasher := BlobsAndCommitments{blobs, commitments}
559-
root := hasher.HashTreeRoot(tree.GetHashFn())
587+
sum, err := sszHash(&BlobsAndCommitments{blobs, commitments})
588+
if err != nil {
589+
return nil, nil, err
590+
}
560591
var r bls.Fr
561-
hashToFr(&r, root)
592+
hashToFr(&r, sum)
562593

563594
powers := computePowers(&r, len(blobs))
564595

@@ -579,9 +610,9 @@ func computeAggregateKzgCommitment(blobs Blobs, commitments []KZGCommitment) ([]
579610
return aggregatePoly, aggregateCommitmentG1, nil
580611
}
581612

582-
func hashToFr(out *bls.Fr, root tree.Root) {
613+
func hashToFr(out *bls.Fr, h [32]byte) {
583614
// re-interpret as little-endian
584-
var b [32]byte = root
615+
var b [32]byte = h
585616
for i := 0; i < 16; i++ {
586617
b[31-i], b[i] = b[i], b[31-i]
587618
}

core/types/hashing.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ package types
1818

1919
import (
2020
"bytes"
21+
"crypto/sha256"
2122
"sync"
2223

24+
"github.com/protolambda/ztyp/codec"
2325
"github.com/protolambda/ztyp/tree"
2426

2527
"github.com/ethereum/go-ethereum/common"
@@ -126,3 +128,14 @@ func DeriveSha(list DerivableList, hasher TrieHasher) common.Hash {
126128
}
127129
return hasher.Hash()
128130
}
131+
132+
// sszHash returns the hash ot the raw serialized ssz-container (i.e. without merkelization)
133+
func sszHash(c codec.Serializable) ([32]byte, error) {
134+
sha := sha256.New()
135+
if err := c.Serialize(codec.NewEncodingWriter(sha)); err != nil {
136+
return [32]byte{}, err
137+
}
138+
var sum [32]byte
139+
copy(sum[:], sha.Sum(nil))
140+
return sum, nil
141+
}

0 commit comments

Comments
 (0)