github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/utils/debug/remoteDebugger.go (about) 1 package debug 2 3 import ( 4 "github.com/onflow/cadence" 5 "github.com/rs/zerolog" 6 7 "github.com/onflow/flow-go/fvm" 8 "github.com/onflow/flow-go/model/flow" 9 ) 10 11 type RemoteDebugger struct { 12 vm fvm.VM 13 ctx fvm.Context 14 grpcAddress string 15 } 16 17 // Warning : make sure you use the proper flow-go version, same version as the network you are collecting registers 18 // from, otherwise the execution might differ from the way runs on the network 19 func NewRemoteDebugger(grpcAddress string, 20 chain flow.Chain, 21 logger zerolog.Logger) *RemoteDebugger { 22 vm := fvm.NewVirtualMachine() 23 24 // no signature processor here 25 // TODO Maybe we add fee-deduction step as well 26 ctx := fvm.NewContext( 27 fvm.WithLogger(logger), 28 fvm.WithChain(chain), 29 fvm.WithAuthorizationChecksEnabled(false), 30 ) 31 32 return &RemoteDebugger{ 33 ctx: ctx, 34 vm: vm, 35 grpcAddress: grpcAddress, 36 } 37 } 38 39 // RunTransaction runs the transaction given the latest sealed block data 40 func (d *RemoteDebugger) RunTransaction( 41 txBody *flow.TransactionBody, 42 ) ( 43 txErr error, 44 processError error, 45 ) { 46 snapshot := NewRemoteStorageSnapshot(d.grpcAddress) 47 defer snapshot.Close() 48 49 blockCtx := fvm.NewContextFromParent( 50 d.ctx, 51 fvm.WithBlockHeader(d.ctx.BlockHeader)) 52 tx := fvm.Transaction(txBody, 0) 53 _, output, err := d.vm.Run(blockCtx, tx, snapshot) 54 if err != nil { 55 return nil, err 56 } 57 return output.Err, nil 58 } 59 60 // RunTransaction runs the transaction and tries to collect the registers at 61 // the given blockID note that it would be very likely that block is far in the 62 // past and you can't find the trie to read the registers from. 63 // if regCachePath is empty, the register values won't be cached 64 func (d *RemoteDebugger) RunTransactionAtBlockID( 65 txBody *flow.TransactionBody, 66 blockID flow.Identifier, 67 regCachePath string, 68 ) ( 69 txErr error, 70 processError error, 71 ) { 72 snapshot := NewRemoteStorageSnapshot(d.grpcAddress, WithBlockID(blockID)) 73 defer snapshot.Close() 74 75 blockCtx := fvm.NewContextFromParent( 76 d.ctx, 77 fvm.WithBlockHeader(d.ctx.BlockHeader)) 78 if len(regCachePath) > 0 { 79 snapshot.Cache = newFileRegisterCache(regCachePath) 80 } 81 tx := fvm.Transaction(txBody, 0) 82 _, output, err := d.vm.Run(blockCtx, tx, snapshot) 83 if err != nil { 84 return nil, err 85 } 86 err = snapshot.Cache.Persist() 87 if err != nil { 88 return nil, err 89 } 90 return output.Err, nil 91 } 92 93 func (d *RemoteDebugger) RunScript( 94 code []byte, 95 arguments [][]byte, 96 ) ( 97 value cadence.Value, 98 scriptError error, 99 processError error, 100 ) { 101 snapshot := NewRemoteStorageSnapshot(d.grpcAddress) 102 defer snapshot.Close() 103 104 scriptCtx := fvm.NewContextFromParent( 105 d.ctx, 106 fvm.WithBlockHeader(d.ctx.BlockHeader)) 107 script := fvm.Script(code).WithArguments(arguments...) 108 _, output, err := d.vm.Run(scriptCtx, script, snapshot) 109 if err != nil { 110 return nil, nil, err 111 } 112 return output.Value, output.Err, nil 113 } 114 115 func (d *RemoteDebugger) RunScriptAtBlockID( 116 code []byte, 117 arguments [][]byte, 118 blockID flow.Identifier, 119 ) ( 120 value cadence.Value, 121 scriptError error, 122 processError error, 123 ) { 124 snapshot := NewRemoteStorageSnapshot(d.grpcAddress, WithBlockID(blockID)) 125 defer snapshot.Close() 126 127 scriptCtx := fvm.NewContextFromParent( 128 d.ctx, 129 fvm.WithBlockHeader(d.ctx.BlockHeader)) 130 script := fvm.Script(code).WithArguments(arguments...) 131 _, output, err := d.vm.Run(scriptCtx, script, snapshot) 132 if err != nil { 133 return nil, nil, err 134 } 135 return output.Value, output.Err, nil 136 }