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  }