Skip to content

Commit 48fedf5

Browse files
authored
Merge pull request #8166 from onflow/bastian/log-traces
[Cadence VM] Improve re-execution tools
2 parents deefc37 + ca0c7dd commit 48fedf5

File tree

4 files changed

+101
-14
lines changed

4 files changed

+101
-14
lines changed

cmd/util/cmd/compare-cadence-vm/cmd.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"golang.org/x/sync/errgroup"
1919

2020
debug_tx "github.com/onflow/flow-go/cmd/util/cmd/debug-tx"
21+
"github.com/onflow/flow-go/fvm"
2122
"github.com/onflow/flow-go/model/flow"
2223
"github.com/onflow/flow-go/module/grpcclient"
2324
"github.com/onflow/flow-go/utils/debug"
@@ -31,6 +32,7 @@ var (
3132
flagUseExecutionDataAPI bool
3233
flagBlockIDs string
3334
flagBlockCount int
35+
flagLogTraces bool
3436
flagWriteTraces bool
3537
flagParallel int
3638
)
@@ -65,6 +67,8 @@ func init() {
6567

6668
Cmd.Flags().IntVar(&flagBlockCount, "block-count", 1, "number of blocks to process (default: 1). if > 1, provide a single block ID with --block-ids")
6769

70+
Cmd.Flags().BoolVar(&flagLogTraces, "log-traces", false, "log traces")
71+
6872
Cmd.Flags().BoolVar(&flagWriteTraces, "write-traces", false, "write traces for mismatched transactions")
6973

7074
Cmd.Flags().IntVar(&flagParallel, "parallel", 1, "number of blocks to process in parallel (default: 1)")
@@ -210,6 +214,12 @@ func compareBlock(
210214

211215
interBlockSnapshot := debug_tx.NewBlockSnapshot(remoteClient, header)
212216

217+
fvmOptions := []fvm.Option{
218+
fvm.WithEntropyProvider(debug_tx.BlockHashEntropyProvider{
219+
BlockHash: blockID,
220+
}),
221+
}
222+
213223
var (
214224
interSpanExporters []*debug.InterestingCadenceSpanExporter
215225
interTxSnapshots []*debug.CapturingStorageSnapshot
@@ -228,11 +238,14 @@ func compareBlock(
228238
return txSnapshot
229239
},
230240
func(_ flow.Identifier) otelTrace.SpanExporter {
231-
exporter := &debug.InterestingCadenceSpanExporter{}
241+
exporter := &debug.InterestingCadenceSpanExporter{
242+
Log: flagLogTraces,
243+
}
232244
interSpanExporters = append(interSpanExporters, exporter)
233245
return exporter
234246
},
235247
flagComputeLimit,
248+
fvmOptions,
236249
)
237250

238251
log.Info().Msg("Running with VM ...")
@@ -257,11 +270,14 @@ func compareBlock(
257270
return txSnapshot
258271
},
259272
func(_ flow.Identifier) otelTrace.SpanExporter {
260-
exporter := &debug.InterestingCadenceSpanExporter{}
273+
exporter := &debug.InterestingCadenceSpanExporter{
274+
Log: flagLogTraces,
275+
}
261276
vmSpanExporters = append(vmSpanExporters, exporter)
262277
return exporter
263278
},
264279
flagComputeLimit,
280+
fvmOptions,
265281
)
266282

267283
var mismatch bool

cmd/util/cmd/debug-tx/cmd.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ var (
3131
flagBlockID string
3232
flagUseVM bool
3333
flagTracePath string
34+
flagLogTraces bool
3435
flagOnlyTraceCadence bool
36+
flagEntropyProvider string
3537
)
3638

3739
var Cmd = &cobra.Command{
@@ -67,7 +69,11 @@ func init() {
6769

6870
Cmd.Flags().StringVar(&flagTracePath, "trace", "", "enable tracing to given path")
6971

72+
Cmd.Flags().BoolVar(&flagLogTraces, "log-cadence-traces", false, "log Cadence traces. requires --trace and --only-trace-cadence to be set (default: false)")
73+
7074
Cmd.Flags().BoolVar(&flagOnlyTraceCadence, "only-trace-cadence", false, "when tracing, only include spans related to Cadence execution (default: false)")
75+
76+
Cmd.Flags().StringVar(&flagEntropyProvider, "entropy-provider", "none", "entropy provider to use (default: none; options: none, block-hash)")
7177
}
7278

7379
func run(_ *cobra.Command, args []string) {
@@ -112,7 +118,9 @@ func run(_ *cobra.Command, args []string) {
112118
var spanExporter otelTrace.SpanExporter
113119
if traceFile != nil {
114120
if flagOnlyTraceCadence {
115-
cadenceSpanExporter := &debug.InterestingCadenceSpanExporter{}
121+
cadenceSpanExporter := &debug.InterestingCadenceSpanExporter{
122+
Log: flagLogTraces,
123+
}
116124
defer func() {
117125
err = cadenceSpanExporter.WriteSpans(traceFile)
118126
if err != nil {
@@ -169,6 +177,7 @@ func run(_ *cobra.Command, args []string) {
169177
nil,
170178
newSpanExporter,
171179
flagComputeLimit,
180+
fvmOptions(blockID),
172181
)
173182

174183
if flagShowResult {
@@ -215,6 +224,22 @@ func run(_ *cobra.Command, args []string) {
215224
}
216225
}
217226

227+
func fvmOptions(blockID flow.Identifier) []fvm.Option {
228+
var options []fvm.Option
229+
230+
switch flagEntropyProvider {
231+
case "block-hash":
232+
options = append(
233+
options,
234+
fvm.WithEntropyProvider(BlockHashEntropyProvider{
235+
BlockHash: blockID,
236+
}),
237+
)
238+
}
239+
240+
return options
241+
}
242+
218243
func RunSingleTransaction(
219244
remoteClient debug.RemoteClient,
220245
txID flow.Identifier,
@@ -268,6 +293,7 @@ func RunSingleTransaction(
268293
nil,
269294
newSpanExporter,
270295
computeLimit,
296+
fvmOptions(blockID),
271297
)
272298

273299
for i, blockTx := range blockTransactions {
@@ -359,6 +385,7 @@ func RunBlock(
359385
wrapTxSnapshot func(blockTxID flow.Identifier, snapshot debug.UpdatableStorageSnapshot) debug.UpdatableStorageSnapshot,
360386
newSpanExporter func(blockTxID flow.Identifier) otelTrace.SpanExporter,
361387
computeLimit uint64,
388+
additionalFVMOptions []fvm.Option,
362389
) (
363390
results []debug.Result,
364391
) {
@@ -390,6 +417,7 @@ func RunBlock(
390417
useVM,
391418
spanExporter,
392419
computeLimit,
420+
additionalFVMOptions,
393421
)
394422

395423
updatedRegisters := result.Snapshot.UpdatedRegisters()
@@ -419,6 +447,7 @@ func RunTransaction(
419447
useVM bool,
420448
spanExporter otelTrace.SpanExporter,
421449
computeLimit uint64,
450+
additionalFVMOptions []fvm.Option,
422451
) debug.Result {
423452

424453
log := log.With().
@@ -452,6 +481,8 @@ func RunTransaction(
452481
)
453482
}
454483

484+
fvmOptions = append(fvmOptions, additionalFVMOptions...)
485+
455486
debugger := debug.NewRemoteDebugger(
456487
chain,
457488
log,
@@ -479,3 +510,14 @@ func RunTransaction(
479510

480511
return result
481512
}
513+
514+
// BlockHashEntropyProvider implements environment.EntropyProvider
515+
// which provides a source of entropy to fvm context (required for Cadence's randomness),
516+
// by using the given block hash.
517+
type BlockHashEntropyProvider struct {
518+
BlockHash flow.Identifier
519+
}
520+
521+
func (p BlockHashEntropyProvider) RandomSource() ([]byte, error) {
522+
return p.BlockHash[:], nil
523+
}

fvm/environment/programs.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/hashicorp/go-multierror"
77
"github.com/onflow/cadence/runtime"
8+
"go.opentelemetry.io/otel/attribute"
89
"golang.org/x/xerrors"
910

1011
"github.com/onflow/cadence"
@@ -91,7 +92,16 @@ func (programs *Programs) GetOrLoadProgram(
9192
location common.Location,
9293
load func() (*runtime.Program, error),
9394
) (*runtime.Program, error) {
94-
defer programs.tracer.StartChildSpan(trace.FVMEnvGetOrLoadProgram).End()
95+
span := programs.tracer.StartChildSpan(trace.FVMEnvGetOrLoadProgram)
96+
defer func() {
97+
if span.Tracer != nil {
98+
span.SetAttributes(
99+
attribute.String("location", location.ID()),
100+
)
101+
}
102+
span.End()
103+
}()
104+
95105
err := programs.meter.MeterComputation(
96106
common.ComputationUsage{
97107
Kind: ComputationKindGetOrLoadProgram,

utils/debug/cadence.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"io"
7+
"os"
78
"slices"
89
"strings"
910

@@ -14,6 +15,7 @@ import (
1415

1516
type InterestingCadenceSpanExporter struct {
1617
Spans []otelTrace.ReadOnlySpan
18+
Log bool
1719
}
1820

1921
var _ otelTrace.SpanExporter = &InterestingCadenceSpanExporter{}
@@ -23,6 +25,7 @@ var interestingSpanNamePrefixes = []trace.SpanName{
2325
trace.FVMEnvAllocateSlabIndex,
2426
trace.FVMEnvGetValue,
2527
trace.FVMEnvSetValue,
28+
trace.FVMEnvGetOrLoadProgram,
2629
}
2730

2831
var uninterestingSpanNames = []trace.SpanName{
@@ -40,6 +43,14 @@ func (s *InterestingCadenceSpanExporter) ExportSpans(_ context.Context, spans []
4043
!slices.Contains(uninterestingSpanNames, trace.SpanName(name)) {
4144

4245
s.Spans = append(s.Spans, span)
46+
47+
if s.Log {
48+
err := writeSpan(os.Stderr, span)
49+
if err != nil {
50+
return err
51+
}
52+
}
53+
4354
break
4455
}
4556
}
@@ -53,26 +64,34 @@ func (s *InterestingCadenceSpanExporter) Shutdown(_ context.Context) error {
5364

5465
func (s *InterestingCadenceSpanExporter) WriteSpans(writer io.Writer) error {
5566
for _, span := range s.Spans {
56-
_, err := fmt.Fprintf(writer, "- %s: ", span.Name())
67+
err := writeSpan(writer, span)
5768
if err != nil {
5869
return err
5970
}
60-
for i, attr := range span.Attributes() {
61-
if i > 0 {
62-
_, err = fmt.Fprintf(writer, ", ")
63-
if err != nil {
64-
return err
65-
}
66-
}
67-
_, err = fmt.Fprintf(writer, "%s=%v", attr.Key, attr.Value.AsInterface())
71+
}
72+
return nil
73+
}
74+
75+
func writeSpan(writer io.Writer, span otelTrace.ReadOnlySpan) error {
76+
_, err := fmt.Fprintf(writer, "- %s: ", span.Name())
77+
if err != nil {
78+
return err
79+
}
80+
for i, attr := range span.Attributes() {
81+
if i > 0 {
82+
_, err = fmt.Fprintf(writer, ", ")
6883
if err != nil {
6984
return err
7085
}
7186
}
72-
_, err = fmt.Fprintln(writer)
87+
_, err = fmt.Fprintf(writer, "%s=%v", attr.Key, attr.Value.AsInterface())
7388
if err != nil {
7489
return err
7590
}
7691
}
92+
_, err = fmt.Fprintln(writer)
93+
if err != nil {
94+
return err
95+
}
7796
return nil
7897
}

0 commit comments

Comments
 (0)