@@ -29,6 +29,7 @@ import (
29
29
"bytes"
30
30
"errors"
31
31
"fmt"
32
+ "sync"
32
33
33
34
"github.com/crate-crypto/go-ipa/banderwagon"
34
35
)
@@ -187,6 +188,7 @@ type (
187
188
188
189
commitment * Point
189
190
c1 , c2 * Point
191
+ cow map [byte ][]byte
190
192
191
193
depth byte
192
194
}
@@ -219,23 +221,6 @@ func NewLeafNode(stem []byte, values [][]byte) *LeafNode {
219
221
c2 : Generator (),
220
222
}
221
223
222
- // Initialize the commitment with the extension tree
223
- // marker and the stem.
224
- cfg := GetConfig ()
225
- count := 0
226
- var poly , c1poly , c2poly [256 ]Fr
227
- poly [0 ].SetUint64 (1 )
228
- StemFromBytes (& poly [1 ], leaf .stem )
229
-
230
- count = fillSuffixTreePoly (c1poly [:], values [:128 ])
231
- leaf .c1 = cfg .CommitToPoly (c1poly [:], 256 - count )
232
- toFr (& poly [2 ], leaf .c1 )
233
- count = fillSuffixTreePoly (c2poly [:], values [128 :])
234
- leaf .c2 = cfg .CommitToPoly (c2poly [:], 256 - count )
235
- toFr (& poly [3 ], leaf .c2 )
236
-
237
- leaf .commitment = cfg .CommitToPoly (poly [:], 252 )
238
-
239
224
return leaf
240
225
}
241
226
@@ -844,7 +829,7 @@ func (n *LeafNode) updateC(index byte, c *Point, oldc *Fr) {
844
829
n .commitment .Add (n .commitment , & diff )
845
830
}
846
831
847
- func (n * LeafNode ) updateCn (index byte , value []byte , c * Point ) {
832
+ func (n * LeafNode ) updateCn (index byte , oldValue []byte , c * Point ) {
848
833
var (
849
834
old , newH [2 ]Fr
850
835
diff Point
@@ -857,8 +842,8 @@ func (n *LeafNode) updateCn(index byte, value []byte, c *Point) {
857
842
// do not include it. The result should be the same,
858
843
// but the computation time should be faster as one doesn't need to
859
844
// compute 1 - 1 mod N.
860
- leafToComms (old [:], n . values [ index ] )
861
- leafToComms (newH [:], value )
845
+ leafToComms (old [:], oldValue )
846
+ leafToComms (newH [:], n . values [ index ] )
862
847
863
848
newH [0 ].Sub (& newH [0 ], & old [0 ])
864
849
poly [2 * (index % 128 )] = newH [0 ]
@@ -873,42 +858,36 @@ func (n *LeafNode) updateCn(index byte, value []byte, c *Point) {
873
858
}
874
859
875
860
func (n * LeafNode ) updateLeaf (index byte , value []byte ) {
876
- c , oldc := n .getOldCn (index )
877
-
878
- n .updateCn (index , value , c )
861
+ // If we haven't calculated a commitment for this node, we don't need to create the cow map since all the
862
+ // previous values are empty. If we already have a calculated commitment, then we track new values in
863
+ // cow so we can do diff-updating in the next Commit().
864
+ if n .commitment != nil {
865
+ // If cow was never setup, then initialize the map.
866
+ if n .cow == nil {
867
+ n .cow = make (map [byte ][]byte )
868
+ }
879
869
880
- n .updateC (index , c , oldc )
870
+ // If we are touching an value in an index for the first time,
871
+ // we save the original value for future use to update commitments.
872
+ if _ , ok := n .cow [index ]; ! ok {
873
+ if n .values [index ] == nil {
874
+ n .cow [index ] = nil
875
+ } else {
876
+ n .cow [index ] = make ([]byte , 32 )
877
+ copy (n .cow [index ], n .values [index ])
878
+ }
879
+ }
880
+ }
881
881
882
882
n .values [index ] = value
883
883
}
884
884
885
885
func (n * LeafNode ) updateMultipleLeaves (values [][]byte ) {
886
- var c1 , c2 * Point
887
- var old1 , old2 * Fr
888
- for i , v := range values {
889
- if len (v ) != 0 && ! bytes .Equal (v , n .values [i ]) {
890
- if i < 128 {
891
- if c1 == nil {
892
- c1 , old1 = n .getOldCn (byte (i ))
893
- }
894
- n .updateCn (byte (i ), v , c1 )
895
- } else {
896
- if c2 == nil {
897
- c2 , old2 = n .getOldCn (byte (i ))
898
- }
899
- n .updateCn (byte (i ), v , c2 )
900
- }
901
-
902
- n .values [i ] = v
886
+ for i := range values {
887
+ if values [i ] != nil {
888
+ n .updateLeaf (byte (i ), values [i ])
903
889
}
904
890
}
905
-
906
- if c1 != nil {
907
- n .updateC (0 , c1 , old1 )
908
- }
909
- if c2 != nil {
910
- n .updateC (128 , c2 , old2 )
911
- }
912
891
}
913
892
914
893
func (n * LeafNode ) InsertOrdered (key []byte , value []byte , _ NodeFlushFn ) error {
@@ -957,8 +936,77 @@ func (n *LeafNode) Commitment() *Point {
957
936
return n .commitment
958
937
}
959
938
960
- func (n * LeafNode ) Commit () * Point {
961
- return n .commitment
939
+ var frPool = sync.Pool {
940
+ New : func () any {
941
+ ret := make ([]Fr , NodeWidth )
942
+ return & ret
943
+ },
944
+ }
945
+
946
+ func (leaf * LeafNode ) Commit () * Point {
947
+ // If we've never calculated a commitment for this leaf node, we calculate the commitment
948
+ // in a single shot considering all the values.
949
+ if leaf .commitment == nil {
950
+ // Initialize the commitment with the extension tree
951
+ // marker and the stem.
952
+ count := 0
953
+ c1polyp := frPool .Get ().(* []Fr )
954
+ c1poly := * c1polyp
955
+ defer func () {
956
+ for i := 0 ; i < 256 ; i ++ {
957
+ c1poly [i ] = Fr {}
958
+ }
959
+ frPool .Put (c1polyp )
960
+ }()
961
+
962
+ count = fillSuffixTreePoly (c1poly , leaf .values [:128 ])
963
+ leaf .c1 = cfg .CommitToPoly (c1poly , 256 - count )
964
+
965
+ for i := 0 ; i < 256 ; i ++ {
966
+ c1poly [i ] = Fr {}
967
+ }
968
+ count = fillSuffixTreePoly (c1poly , leaf .values [128 :])
969
+ leaf .c2 = cfg .CommitToPoly (c1poly , 256 - count )
970
+
971
+ for i := 0 ; i < 256 ; i ++ {
972
+ c1poly [i ] = Fr {}
973
+ }
974
+ c1poly [0 ].SetUint64 (1 )
975
+ StemFromBytes (& c1poly [1 ], leaf .stem )
976
+
977
+ toFrMultiple ([]* Fr {& c1poly [2 ], & c1poly [3 ]}, []* Point {leaf .c1 , leaf .c2 })
978
+ leaf .commitment = cfg .CommitToPoly (c1poly , 252 )
979
+
980
+ } else if len (leaf .cow ) != 0 {
981
+ // If we've already have a calculated commitment, and there're touched leaf values, we do a diff update.
982
+ var c1 , c2 * Point
983
+ var old1 , old2 * Fr
984
+ for i , oldValue := range leaf .cow {
985
+ if ! bytes .Equal (oldValue , leaf .values [i ]) {
986
+ if i < 128 {
987
+ if c1 == nil {
988
+ c1 , old1 = leaf .getOldCn (i )
989
+ }
990
+ leaf .updateCn (i , oldValue , c1 )
991
+ } else {
992
+ if c2 == nil {
993
+ c2 , old2 = leaf .getOldCn (i )
994
+ }
995
+ leaf .updateCn (i , oldValue , c2 )
996
+ }
997
+ }
998
+ }
999
+
1000
+ if c1 != nil {
1001
+ leaf .updateC (0 , c1 , old1 )
1002
+ }
1003
+ if c2 != nil {
1004
+ leaf .updateC (128 , c2 , old2 )
1005
+ }
1006
+ leaf .cow = nil
1007
+ }
1008
+
1009
+ return leaf .commitment
962
1010
}
963
1011
964
1012
// fillSuffixTreePoly takes one of the two suffix tree and
0 commit comments