-
Notifications
You must be signed in to change notification settings - Fork 166
/
remoteDebugger.go
136 lines (122 loc) · 3.34 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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.VM
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.WithAuthorizationChecksEnabled(false),
)
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 error,
processError error,
) {
snapshot := NewRemoteStorageSnapshot(d.grpcAddress)
defer snapshot.Close()
blockCtx := fvm.NewContextFromParent(
d.ctx,
fvm.WithBlockHeader(d.ctx.BlockHeader))
tx := fvm.Transaction(txBody, 0)
_, output, err := d.vm.Run(blockCtx, tx, snapshot)
if err != nil {
return nil, err
}
return output.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 error,
processError error,
) {
snapshot := NewRemoteStorageSnapshot(d.grpcAddress, WithBlockID(blockID))
defer snapshot.Close()
blockCtx := fvm.NewContextFromParent(
d.ctx,
fvm.WithBlockHeader(d.ctx.BlockHeader))
if len(regCachePath) > 0 {
snapshot.Cache = newFileRegisterCache(regCachePath)
}
tx := fvm.Transaction(txBody, 0)
_, output, err := d.vm.Run(blockCtx, tx, snapshot)
if err != nil {
return nil, err
}
err = snapshot.Cache.Persist()
if err != nil {
return nil, err
}
return output.Err, nil
}
func (d *RemoteDebugger) RunScript(
code []byte,
arguments [][]byte,
) (
value cadence.Value,
scriptError error,
processError error,
) {
snapshot := NewRemoteStorageSnapshot(d.grpcAddress)
defer snapshot.Close()
scriptCtx := fvm.NewContextFromParent(
d.ctx,
fvm.WithBlockHeader(d.ctx.BlockHeader))
script := fvm.Script(code).WithArguments(arguments...)
_, output, err := d.vm.Run(scriptCtx, script, snapshot)
if err != nil {
return nil, nil, err
}
return output.Value, output.Err, nil
}
func (d *RemoteDebugger) RunScriptAtBlockID(
code []byte,
arguments [][]byte,
blockID flow.Identifier,
) (
value cadence.Value,
scriptError error,
processError error,
) {
snapshot := NewRemoteStorageSnapshot(d.grpcAddress, WithBlockID(blockID))
defer snapshot.Close()
scriptCtx := fvm.NewContextFromParent(
d.ctx,
fvm.WithBlockHeader(d.ctx.BlockHeader))
script := fvm.Script(code).WithArguments(arguments...)
_, output, err := d.vm.Run(scriptCtx, script, snapshot)
if err != nil {
return nil, nil, err
}
return output.Value, output.Err, nil
}