Skip to content

Commit 4c8f1f5

Browse files
committed
improve readability
Signed-off-by: Ignacio Hagopian <[email protected]>
1 parent d011c02 commit 4c8f1f5

File tree

2 files changed

+57
-31
lines changed

2 files changed

+57
-31
lines changed

config_ipa.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ type IPAConfig struct {
3838
type Config = IPAConfig
3939

4040
func (ipac *IPAConfig) CommitToPoly(poly []Fr, _ int) *Point {
41-
c := ipac.conf.Commit(poly)
42-
return &c
41+
ret := ipac.conf.Commit(poly)
42+
return &ret
4343
}
4444

4545
var cfg *Config
@@ -69,10 +69,8 @@ func GetConfig() *Config {
6969
return cfg
7070
}
7171

72-
var (
73-
FrZero Fr
74-
FrOne Fr
75-
)
72+
var FrZero Fr
73+
var FrOne Fr
7674

7775
func init() {
7876
FrZero.SetZero()

tree.go

+53-25
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,10 @@ func (n *InternalNode) Delete(key []byte, resolver NodeResolverFn) error {
469469
func (n *InternalNode) Flush(flush NodeFlushFn) {
470470
n.Commit()
471471

472-
if n.depth <= 0 {
472+
// If we're at the root internal node, we fire goroutines exploiting
473+
// available cores. Those goroutines will recursively take care of downstream
474+
// layers, so we avoid creating too many goroutines.
475+
if n.depth == 0 {
473476
batches := runtime.NumCPU()
474477
batchSize := len(n.children) / batches
475478
var wg sync.WaitGroup
@@ -585,8 +588,12 @@ func (n *InternalNode) Commitment() *Point {
585588
}
586589

587590
func (n *InternalNode) Commit() *Point {
591+
// If we're at the first or second layer, we do the Commit() in parallel
592+
// leveraging available cores.
593+
// If we're in further layers, we do single-goroutine Commit() since the top
594+
// two layers already created enough goroutines doing downstream work.
588595
if n.depth <= 1 {
589-
return n.commitRoot()
596+
return n.commitParallel()
590597
}
591598
if len(n.cow) != 0 {
592599
polyp := frPool.Get().(*[]Fr)
@@ -627,7 +634,7 @@ func (n *InternalNode) Commit() *Point {
627634
return n.commitment
628635
}
629636

630-
func (n *InternalNode) commitRoot() *Point {
637+
func (n *InternalNode) commitParallel() *Point {
631638
if len(n.cow) != 0 {
632639
polyp := frPool.Get().(*[]Fr)
633640
poly := *polyp
@@ -639,50 +646,74 @@ func (n *InternalNode) commitRoot() *Point {
639646
}()
640647
emptyChildren := 256
641648

649+
// The idea below is to distribute calling Commit() in all COW-ed children in multiple goroutines.
650+
// For example, if we have 2-cores, we calculate the first half of COW-ed new Commit() in a goroutine, and
651+
// the other half in another goroutine.
652+
653+
// In `points` we'll have:
654+
// - point[2*i]: the previous *Point value saved by COW.
655+
// - point[2*i+1]: we'll calculate the new Commit() of that leaf value.
656+
//
657+
// First, we create the arrays to store this.
642658
var i int
643-
b := make([]byte, len(n.cow))
659+
pointsIndexes := make([]byte, len(n.cow))
644660
points := make([]*Point, 2*len(n.cow))
645661
for idx := range n.cow {
646662
emptyChildren--
647-
b[i] = idx
663+
pointsIndexes[i] = idx
648664
i++
649665
}
650666

651667
var wg sync.WaitGroup
652-
f := func(start, end int) {
668+
// `calculateChildsCommsInRange` does the mentioned calculation in `points`.
669+
// It receives the range in the array where it should do the work. As mentioned earlier, each goroutine
670+
// is assigned a range to do work. The complete range work is distributed in multiple goroutines.
671+
calculateChildsCommsInRange := func(start, end int) {
653672
defer wg.Done()
654673
for i := start; i < end; i++ {
655-
points[2*i] = n.cow[b[i]]
656-
points[2*i+1] = n.children[b[i]].Commit()
674+
points[2*i] = n.cow[pointsIndexes[i]]
675+
points[2*i+1] = n.children[pointsIndexes[i]].Commit()
657676
}
658677
}
678+
// Here we do the work distribution. We split the total range of work to do in `numBatches` batches and call
679+
// the above function which does the work.
659680
numBatches := runtime.NumCPU()
660681
wg.Add(numBatches)
661682
for i := 0; i < numBatches; i++ {
683+
batchStart := i * (len(pointsIndexes) / numBatches)
662684
if i < numBatches-1 {
663-
go f(i*(len(b)/numBatches), (i+1)*(len(b)/numBatches))
685+
go calculateChildsCommsInRange(batchStart, (i+1)*(len(pointsIndexes)/numBatches))
664686
} else {
665-
go f(i*(len(b)/numBatches), len(b))
687+
go calculateChildsCommsInRange(batchStart, len(pointsIndexes))
666688
}
667689
}
668690

691+
// After calculating the new *Point (Commit() of touched children), we'll have to do the Point->Fr transformation.
669692
frs := make([]*Fr, len(points))
670693
for i := range frs {
671694
if i%2 == 0 {
695+
// For even slots (old COW commitment), we create a new empty Fr to store the result.
672696
frs[i] = &Fr{}
673697
} else {
674-
frs[i] = &poly[b[i/2]]
698+
// For odd slots (new commitment), we can use `poly` as a temporal storage to avoid allocations.
699+
frs[i] = &poly[pointsIndexes[i/2]]
675700
}
676701
}
677702
wg.Wait()
678703

704+
// Now that in `frs` we have where we want to store *all* the Point->Fr transformations, we do that in a single batch.
679705
toFrMultiple(frs, points)
706+
707+
// For each
680708
for i := 0; i < len(points)/2; i++ {
681-
poly[b[i]].Sub(frs[2*i+1], frs[2*i])
709+
// Now we do [newCommitment] - [oldCommitment], so we know the Fr difference between old and new commitments.
710+
poly[pointsIndexes[i]].Sub(frs[2*i+1], frs[2*i])
682711
}
683712

684713
n.cow = nil
685714

715+
// Now that in `poly` we have the Fr differences, we `CommitToPoly` and add to the current internal node
716+
// commitment, finishing the diff-updating.
686717
n.commitment.Add(n.commitment, cfg.CommitToPoly(poly, emptyChildren))
687718
return n.commitment
688719
}
@@ -1114,24 +1145,15 @@ func (leaf *LeafNode) Commit() *Point {
11141145
// Initialize the commitment with the extension tree
11151146
// marker and the stem.
11161147
count := 0
1117-
polyp, c1polyp := frPool.Get().(*[]Fr), frPool.Get().(*[]Fr)
1118-
// TODO(jsign): remove "poly" and reuse again c1poly
1119-
poly, c1poly := *polyp, *c1polyp
1148+
c1polyp := frPool.Get().(*[]Fr)
1149+
c1poly := *c1polyp
11201150
defer func() {
11211151
for i := 0; i < 256; i++ {
1122-
poly[i] = Fr{}
11231152
c1poly[i] = Fr{}
11241153
}
1125-
frPool.Put(polyp)
11261154
frPool.Put(c1polyp)
11271155
}()
1128-
poly[0].SetUint64(1)
1129-
StemFromBytes(&poly[1], leaf.stem)
11301156

1131-
// TODO(jsign)
1132-
if len(leaf.values) != 256 {
1133-
panic("leaf doesn't have 256 values")
1134-
}
11351157
count = fillSuffixTreePoly(c1poly[:], leaf.values[:128])
11361158
leaf.c1 = cfg.CommitToPoly(c1poly[:], 256-count)
11371159

@@ -1141,8 +1163,14 @@ func (leaf *LeafNode) Commit() *Point {
11411163
count = fillSuffixTreePoly(c1poly[:], leaf.values[128:])
11421164
leaf.c2 = cfg.CommitToPoly(c1poly[:], 256-count)
11431165

1144-
toFrMultiple([]*Fr{&poly[2], &poly[3]}, []*Point{leaf.c1, leaf.c2})
1145-
leaf.commitment = cfg.CommitToPoly(poly[:], 252)
1166+
for i := 0; i < 256; i++ {
1167+
c1poly[i] = Fr{}
1168+
}
1169+
c1poly[0].SetUint64(1)
1170+
StemFromBytes(&c1poly[1], leaf.stem)
1171+
1172+
toFrMultiple([]*Fr{&c1poly[2], &c1poly[3]}, []*Point{leaf.c1, leaf.c2})
1173+
leaf.commitment = cfg.CommitToPoly(c1poly[:], 252)
11461174

11471175
} else if len(leaf.cow) != 0 {
11481176
// If we've already have a calculated commitment, and there're touched leaf values, we do a diff update.

0 commit comments

Comments
 (0)