Skip to content

Commit 314caa9

Browse files
committed
validator benchmarks + refactoring
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
1 parent 0199a53 commit 314caa9

File tree

49 files changed

+3034
-1863
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3034
-1863
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ clean-fabric-peer-images:
135135
tokengen:
136136
@go install ./cmd/tokengen
137137

138+
.PHONY: traceinspector
139+
traceinspector:
140+
@go install ./token/services/benchmark/cmd/traceinspector
141+
142+
.PHONY: memcheck
143+
memcheck:
144+
@go install ./token/services/benchmark/cmd/memcheck
145+
138146
.PHONY: idemixgen
139147
txgen:
140148
@go install github.com/IBM/idemix/tools/idemixgen

cmd/tokengen/cobra/pp/common/common_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
77
package common
88

99
import (
10+
"bytes"
1011
"os"
1112
"path/filepath"
1213
"testing"
@@ -45,11 +46,11 @@ func TestLoadExtras(t *testing.T) {
4546
t.Errorf("expected 2 entries, got %d", len(result))
4647
}
4748

48-
if string(result["foo"]) != string(file1Content) {
49+
if !bytes.Equal(result["foo"], file1Content) {
4950
t.Errorf("expected %q for foo, got %q", string(file1Content), string(result["foo"]))
5051
}
5152

52-
if string(result["bar"]) != string(file2Content) {
53+
if !bytes.Equal(result["bar"], file2Content) {
5354
t.Errorf("expected %q for bar, got %q", string(file2Content), string(result["bar"]))
5455
}
5556
})
@@ -144,7 +145,7 @@ func TestLoadExtras(t *testing.T) {
144145
t.Fatalf("expected no error, got: %v", err)
145146
}
146147

147-
if string(result["mykey"]) != string(fileContent) {
148+
if !bytes.Equal(result["mykey"], fileContent) {
148149
t.Errorf("expected %q, got %q", string(fileContent), string(result["mykey"]))
149150
}
150151
})

docs/benchmark/dlognogh/dlognogh.md

Lines changed: 65 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Packages with benchmark tests:
66
- `BenchmarkSender`, `BenchmarkVerificationSenderProof`, `TestParallelBenchmarkSender`, and `TestParallelBenchmarkVerificationSenderProof` are used to benchmark the generation of a transfer action. This includes also the generation of ZK proof for a transfer operation.
77
- `BenchmarkTransferProofGeneration`, `TestParallelBenchmarkTransferProofGeneration` are used to benchmark the generation of ZK proof alone.
88
- `token/core/zkatdlog/nogh/v1/issue`: `BenchmarkIssuer` and `BenchmarkProofVerificationIssuer`
9-
- `token/core/zkatdlog/nogh/v1`: `BenchmarkTransfer`
9+
- `token/core/zkatdlog/nogh/v1/validator`: `TestParallelBenchmarkValidatorTransfer`.
10+
- `token/core/zkatdlog/nogh/v1`: `BenchmarkTransferServiceTransfer` and `TestParallelBenchmarkTransferServiceTransfer`.
1011

1112
The steps necessary to run the benchmarks are very similar.
1213
We give two examples here:
@@ -116,10 +117,10 @@ Example results have been produced on an Apple M1 Max and can be consulted [here
116117
This is a test that runs multiple instances of the above benchmark in parallel.
117118
This allows the analyst to understand if shared data structures are actual bottlenecks.
118119

119-
It uses a custom-made runner whose documentation can be found [here](../../../token/core/common/benchmark/runner.md).
120+
It uses a custom-made runner whose documentation can be found [here](../../../token/services/benchmark/runner.md).
120121

121122
```shell
122-
go test ./token/core/zkatdlog/nogh/v1/transfer -test.run=TestParallelBenchmarkSender -test.v -test.benchmem -test.timeout 0 -bits="32" -curves="BN254" -num_inputs="2" -num_outputs="2" -workers="1,10" -duration="10s" | tee bench.txt
123+
go test ./token/core/zkatdlog/nogh/v1/transfer -test.run=TestParallelBenchmarkSender -test.v -test.timeout 0 -bits="32" -curves="BN254" -num_inputs="2" -num_outputs="2" -workers="NumCPU" -duration="10s" -setup_samples=128 | tee bench.txt
123124
```
124125

125126
The test supports the following flags:
@@ -136,120 +137,82 @@ The test supports the following flags:
136137
a comma-separate list of number of outputs (1,2,3,...)
137138
-workers string
138139
a comma-separate list of workers (1,2,3,...,NumCPU), where NumCPU is converted to the number of available CPUs
140+
-profile bool
141+
write pprof profiles to file
142+
-setup_samples uint
143+
number of setup samples, 0 disables it
139144
```
140145

141146
### Results
142147

143-
```go
148+
```shell
144149
=== RUN TestParallelBenchmarkSender
145-
=== RUN TestParallelBenchmarkSender/Setup(bits_32,_curve_BN254,_#i_2,_#o_2)_with_1_workers
146-
Metric Value Description
147-
------ ----- -----------
148-
Workers 1
149-
Total Ops 168 (Low Sample Size)
150-
Duration 10.023390959s (Good Duration)
151-
Real Throughput 16.76/s Observed Ops/sec (Wall Clock)
152-
Pure Throughput 17.77/s Theoretical Max (Low Overhead)
153-
154-
Latency Distribution:
155-
Min 55.180375ms
156-
P50 (Median) 55.945812ms
157-
Average 56.290356ms
158-
P95 58.108814ms
159-
P99 58.758087ms
160-
Max 59.089958ms (Stable Tail)
161-
162-
Stability Metrics:
163-
Std Dev 898.087µs
164-
IQR 1.383083ms Interquartile Range
165-
Jitter 590.076µs Avg delta per worker
166-
CV 1.60% Excellent Stability (<5%)
167-
168-
Memory 1301420 B/op Allocated bytes per operation
169-
Allocs 18817 allocs/op Allocations per operation
170-
171-
Latency Heatmap (Dynamic Range):
172-
Range Freq Distribution Graph
173-
55.180375ms-55.369563ms 17 █████████████████████████ (10.1%)
174-
55.369563ms-55.5594ms 18 ██████████████████████████ (10.7%)
175-
55.5594ms-55.749887ms 27 ████████████████████████████████████████ (16.1%)
176-
55.749887ms-55.941028ms 20 █████████████████████████████ (11.9%)
177-
55.941028ms-56.132824ms 13 ███████████████████ (7.7%)
178-
56.132824ms-56.325277ms 9 █████████████ (5.4%)
179-
56.325277ms-56.51839ms 4 █████ (2.4%)
180-
56.51839ms-56.712165ms 6 ████████ (3.6%)
181-
56.712165ms-56.906605ms 9 █████████████ (5.4%)
182-
56.906605ms-57.101711ms 13 ███████████████████ (7.7%)
183-
57.101711ms-57.297486ms 10 ██████████████ (6.0%)
184-
57.297486ms-57.493933ms 3 ████ (1.8%)
185-
57.493933ms-57.691053ms 3 ████ (1.8%)
186-
57.691053ms-57.888849ms 4 █████ (2.4%)
187-
57.888849ms-58.087323ms 3 ████ (1.8%)
188-
58.087323ms-58.286478ms 2 ██ (1.2%)
189-
58.286478ms-58.486315ms 2 ██ (1.2%)
190-
58.486315ms-58.686837ms 2 ██ (1.2%)
191-
58.686837ms-58.888047ms 2 ██ (1.2%)
192-
58.888047ms-59.089958ms 1 █ (0.6%)
193-
194-
--- Analysis & Recommendations ---
195-
[WARN] Low sample size (168). Results may not be statistically significant. Run for longer.
196-
[INFO] High Allocations (18817/op). This will trigger frequent GC cycles and increase Max Latency.
197-
----------------------------------
198150
=== RUN TestParallelBenchmarkSender/Setup(bits_32,_curve_BN254,_#i_2,_#o_2)_with_10_workers
199-
Metric Value Description
200-
------ ----- -----------
201-
Workers 10
202-
Total Ops 1232 (Low Sample Size)
203-
Duration 10.070877291s (Good Duration)
204-
Real Throughput 122.33/s Observed Ops/sec (Wall Clock)
205-
Pure Throughput 130.12/s Theoretical Max (Low Overhead)
151+
Metric Value Description
152+
------ ----- -----------
153+
Workers 10
154+
Total Ops 1230 (Low Sample Size)
155+
Duration 10.068s (Good Duration)
156+
Real Throughput 122.17/s Observed Ops/sec (Wall Clock)
157+
Pure Throughput 123.04/s Theoretical Max (Low Overhead)
206158

207159
Latency Distribution:
208-
Min 61.2545ms
209-
P50 (Median) 75.461375ms
210-
Average 76.852256ms
211-
P95 93.50851ms
212-
P99 106.198982ms
213-
Max 144.872375ms (Stable Tail)
160+
Min 59.895916ms
161+
P50 (Median) 77.717333ms
162+
Average 81.27214ms
163+
P95 112.28194ms
164+
P99 137.126207ms
165+
P99.9 189.117473ms
166+
Max 215.981417ms (Stable Tail)
214167

215168
Stability Metrics:
216-
Std Dev 9.28799ms
217-
IQR 10.909229ms Interquartile Range
218-
Jitter 9.755984ms Avg delta per worker
219-
CV 12.09% Moderate Variance (10-20%)
220-
221-
Memory 1282384 B/op Allocated bytes per operation
222-
Allocs 18668 allocs/op Allocations per operation
169+
Std Dev 16.96192ms
170+
IQR 19.050834ms Interquartile Range
171+
Jitter 15.937043ms Avg delta per worker
172+
CV 20.87% Unstable (>20%) - Result is Noisy
173+
174+
System Health & Reliability:
175+
Error Rate 0.0000% (100% Success) (0 errors)
176+
Memory 1159374 B/op Allocated bytes per operation
177+
Allocs 17213 allocs/op Allocations per operation
178+
Alloc Rate 133.20 MB/s Memory pressure on system
179+
GC Overhead 1.27% (High GC Pressure)
180+
GC Pause 127.435871ms Total Stop-The-World time
181+
GC Cycles 264 Full garbage collection cycles
223182

224183
Latency Heatmap (Dynamic Range):
225184
Range Freq Distribution Graph
226-
61.2545ms-63.948502ms 36 ███████ (2.9%)
227-
63.948502ms-66.760987ms 86 █████████████████ (7.0%)
228-
66.760987ms-69.697167ms 152 ███████████████████████████████ (12.3%)
229-
69.697167ms-72.762481ms 181 █████████████████████████████████████ (14.7%)
230-
72.762481ms-75.962609ms 195 ████████████████████████████████████████ (15.8%)
231-
75.962609ms-79.303481ms 179 ████████████████████████████████████ (14.5%)
232-
79.303481ms-82.791286ms 152 ███████████████████████████████ (12.3%)
233-
82.791286ms-86.432486ms 94 ███████████████████ (7.6%)
234-
86.432486ms-90.233828ms 59 ████████████ (4.8%)
235-
90.233828ms-94.202355ms 40 ████████ (3.2%)
236-
94.202355ms-98.345419ms 29 █████ (2.4%)
237-
98.345419ms-102.670697ms 9 █ (0.7%)
238-
102.670697ms-107.186203ms 8 █ (0.6%)
239-
107.186203ms-111.900303ms 4 (0.3%)
240-
111.900303ms-116.821732ms 2 (0.2%)
241-
116.821732ms-121.959608ms 3 (0.2%)
242-
121.959608ms-127.32345ms 1 (0.1%)
243-
127.32345ms-132.923196ms 1 (0.1%)
244-
138.769222ms-144.872375ms 1 (0.1%)
185+
59.895916ms-63.862831ms 98 ██████████████████████ (8.0%)
186+
63.862831ms-68.092476ms 163 ████████████████████████████████████ (13.3%)
187+
68.092476ms-72.602251ms 170 ██████████████████████████████████████ (13.8%)
188+
72.602251ms-77.410709ms 172 █████████████████████████████████████ (14.0%)
189+
77.410709ms-82.537631ms 177 ████████████████████████████████████████ (14.4%)
190+
82.537631ms-88.004111ms 128 ████████████████████████████ (10.4%)
191+
88.004111ms-93.832637ms 119 ██████████████████████████ (9.7%)
192+
93.832637ms-100.047186ms 73 ████████████████ (5.9%)
193+
100.047186ms-106.673326ms 40 █████████ (3.3%)
194+
106.673326ms-113.738317ms 32 ███████ (2.6%)
195+
113.738317ms-121.271222ms 20 ████ (1.6%)
196+
121.271222ms-129.303034ms 14 ███ (1.1%)
197+
129.303034ms-137.866793ms 12 ██ (1.0%)
198+
137.866793ms-146.997731ms 3 (0.2%)
199+
146.997731ms-156.733413ms 4 (0.3%)
200+
167.11389ms-178.181868ms 2 (0.2%)
201+
178.181868ms-189.98288ms 1 (0.1%)
202+
189.98288ms-202.565475ms 1 (0.1%)
203+
202.565475ms-215.981417ms 1 (0.1%)
245204

246205
--- Analysis & Recommendations ---
247-
[WARN] Low sample size (1232). Results may not be statistically significant. Run for longer.
248-
[INFO] High Allocations (18668/op). This will trigger frequent GC cycles and increase Max Latency.
206+
[WARN] Low sample size (1230). Results may not be statistically significant. Run for longer.
207+
[FAIL] High Variance (CV 20.87%). System noise is affecting results. Isolate the machine or increase duration.
208+
[INFO] High Allocations (17213/op). This will trigger frequent GC cycles and increase Max Latency.
249209
----------------------------------
250-
--- PASS: TestParallelBenchmarkSender (20.83s)
251-
--- PASS: TestParallelBenchmarkSender/Setup(bits_32,_curve_BN254,_#i_2,_#o_2)_with_1_workers (10.39s)
252-
--- PASS: TestParallelBenchmarkSender/Setup(bits_32,_curve_BN254,_#i_2,_#o_2)_with_10_workers (10.44s)
210+
211+
--- Throughput Timeline ---
212+
Timeline: [▇▇▇█▇▇▇▇▆▇] (Max: 131 ops/s)
213+
214+
--- PASS: TestParallelBenchmarkSender (13.97s)
215+
--- PASS: TestParallelBenchmarkSender/Setup(bits_32,_curve_BN254,_#i_2,_#o_2)_with_10_workers (13.96s)
253216
PASS
254-
ok github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/transfer 21.409s
217+
ok github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/transfer 14.566s
255218
```

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ require (
3535
go.uber.org/dig v1.18.0
3636
go.uber.org/zap v1.27.0
3737
golang.org/x/crypto v0.45.0
38-
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
38+
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39
3939
golang.org/x/sync v0.18.0
4040
google.golang.org/protobuf v1.36.10
4141
gopkg.in/yaml.v2 v2.4.0
@@ -282,14 +282,14 @@ require (
282282
go.uber.org/multierr v1.11.0 // indirect
283283
go.yaml.in/yaml/v3 v3.0.4 // indirect
284284
golang.org/x/arch v0.11.0 // indirect
285-
golang.org/x/mod v0.29.0 // indirect
285+
golang.org/x/mod v0.30.0 // indirect
286286
golang.org/x/net v0.47.0 // indirect
287287
golang.org/x/oauth2 v0.30.0 // indirect
288288
golang.org/x/sys v0.38.0 // indirect
289-
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
289+
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect
290290
golang.org/x/text v0.31.0 // indirect
291291
golang.org/x/time v0.8.0 // indirect
292-
golang.org/x/tools v0.38.0 // indirect
292+
golang.org/x/tools v0.39.0 // indirect
293293
gonum.org/v1/gonum v0.16.0 // indirect
294294
google.golang.org/api v0.215.0 // indirect
295295
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,8 +1702,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
17021702
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
17031703
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
17041704
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
1705-
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
1706-
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
1705+
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 h1:DHNhtq3sNNzrvduZZIiFyXWOL9IWaDPHqTnLJp+rCBY=
1706+
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0=
17071707
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
17081708
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
17091709
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1750,8 +1750,8 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
17501750
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
17511751
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
17521752
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
1753-
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
1754-
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
1753+
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
1754+
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
17551755
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
17561756
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
17571757
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1975,8 +1975,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
19751975
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
19761976
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
19771977
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
1978-
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
1979-
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
1978+
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo=
1979+
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ=
19801980
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
19811981
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
19821982
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2095,8 +2095,8 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
20952095
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
20962096
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
20972097
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
2098-
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
2099-
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
2098+
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
2099+
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
21002100
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
21012101
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
21022102
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

0 commit comments

Comments
 (0)