-
Notifications
You must be signed in to change notification settings - Fork 178
/
remoteDebugger.go
98 lines (87 loc) · 3.12 KB
/
remoteDebugger.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package debug
import (
"github.com/onflow/cadence"
"github.com/rs/zerolog"
"github.com/onflow/flow-go/fvm"
"github.com/onflow/flow-go/model/flow"
)
type RemoteDebugger struct {
vm *fvm.VirtualMachine
ctx fvm.Context
grpcAddress string
}
// Warning : make sure you use the proper flow-go version, same version as the network you are collecting registers
// from, otherwise the execution might differ from the way runs on the network
func NewRemoteDebugger(grpcAddress string,
chain flow.Chain,
logger zerolog.Logger) *RemoteDebugger {
vm := fvm.NewVirtualMachine()
// no signature processor here
// TODO Maybe we add fee-deduction step as well
ctx := fvm.NewContext(
fvm.WithLogger(logger),
fvm.WithChain(chain),
fvm.WithTransactionProcessors(
fvm.NewTransactionSequenceNumberChecker(),
fvm.NewTransactionInvoker(),
),
)
return &RemoteDebugger{
ctx: ctx,
vm: vm,
grpcAddress: grpcAddress,
}
}
// RunTransaction runs the transaction given the latest sealed block data
func (d *RemoteDebugger) RunTransaction(txBody *flow.TransactionBody) (txErr, processError error) {
view := NewRemoteView(d.grpcAddress)
blockCtx := fvm.NewContextFromParent(d.ctx, fvm.WithBlockHeader(d.ctx.BlockHeader))
tx := fvm.Transaction(txBody, 0)
err := d.vm.Run(blockCtx, tx, view)
if err != nil {
return nil, err
}
return tx.Err, nil
}
// RunTransaction runs the transaction and tries to collect the registers at the given blockID
// note that it would be very likely that block is far in the past and you can't find the trie to
// read the registers from
// if regCachePath is empty, the register values won't be cached
func (d *RemoteDebugger) RunTransactionAtBlockID(txBody *flow.TransactionBody, blockID flow.Identifier, regCachePath string) (txErr, processError error) {
view := NewRemoteView(d.grpcAddress, WithBlockID(blockID))
defer view.Done()
blockCtx := fvm.NewContextFromParent(d.ctx, fvm.WithBlockHeader(d.ctx.BlockHeader))
if len(regCachePath) > 0 {
view.Cache = newFileRegisterCache(regCachePath)
}
tx := fvm.Transaction(txBody, 0)
err := d.vm.Run(blockCtx, tx, view)
if err != nil {
return nil, err
}
err = view.Cache.Persist()
if err != nil {
return nil, err
}
return tx.Err, nil
}
func (d *RemoteDebugger) RunScript(code []byte, arguments [][]byte) (value cadence.Value, scriptError, processError error) {
view := NewRemoteView(d.grpcAddress)
scriptCtx := fvm.NewContextFromParent(d.ctx, fvm.WithBlockHeader(d.ctx.BlockHeader))
script := fvm.Script(code).WithArguments(arguments...)
err := d.vm.Run(scriptCtx, script, view)
if err != nil {
return nil, nil, err
}
return script.Value, script.Err, nil
}
func (d *RemoteDebugger) RunScriptAtBlockID(code []byte, arguments [][]byte, blockID flow.Identifier) (value cadence.Value, scriptError, processError error) {
view := NewRemoteView(d.grpcAddress, WithBlockID(blockID))
scriptCtx := fvm.NewContextFromParent(d.ctx, fvm.WithBlockHeader(d.ctx.BlockHeader))
script := fvm.Script(code).WithArguments(arguments...)
err := d.vm.Run(scriptCtx, script, view)
if err != nil {
return nil, nil, err
}
return script.Value, script.Err, nil
}