Skip to content

Commit 69fa06c

Browse files
Track procedure program depedencies
1 parent def6a7b commit 69fa06c

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

fvm/environment/facade_env.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ func (env *facadeEnvironment) FlushPendingUpdates() (
286286
func (env *facadeEnvironment) Reset() {
287287
env.ContractUpdater.Reset()
288288
env.EventEmitter.Reset()
289+
env.Programs.Reset()
289290
}
290291

291292
// Miscellaneous cadence runtime.Interface API.

fvm/environment/programs.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ func NewPrograms(
5959
}
6060
}
6161

62+
// Reset resets the program cache.
63+
// this is called if the transactions happy path fails.
64+
func (programs *Programs) Reset() {
65+
programs.nonAddressPrograms = make(map[common.Location]*interpreter.Program)
66+
programs.dependencyStack = newDependencyStack()
67+
}
68+
6269
// GetOrLoadProgram gets the program from the cache,
6370
// or loads it (by calling load) if it is not in the cache.
6471
// When loading a program, this method will be re-entered
@@ -288,9 +295,18 @@ type dependencyStack struct {
288295
}
289296

290297
func newDependencyStack() *dependencyStack {
291-
return &dependencyStack{
298+
stack := &dependencyStack{
292299
trackers: make([]dependencyTracker, 0),
293300
}
301+
302+
// The root of the stack is the program (script/transaction) that is being executed.
303+
// At the end of the transaction execution, this will hold all the dependencies
304+
// of the script/transaction.
305+
//
306+
// The root of the stack should never be popped.
307+
stack.push(common.StringLocation("^ProgramDependencyStackRoot$"))
308+
309+
return stack
294310
}
295311

296312
// push a new location to track dependencies for.
@@ -311,17 +327,16 @@ func (s *dependencyStack) push(loc common.Location) {
311327
func (s *dependencyStack) add(dependencies derived.ProgramDependencies) {
312328
l := len(s.trackers)
313329
if l == 0 {
314-
// stack is empty.
315-
// This is expected if loading a program that is already cached.
316-
return
330+
// This cannot happen, as the root of the stack is always present.
331+
panic("Dependency stack unexpectedly empty")
317332
}
318333

319334
s.trackers[l-1].dependencies.Merge(dependencies)
320335
}
321336

322337
// pop the last dependencies on the stack and return them.
323338
func (s *dependencyStack) pop() (common.Location, derived.ProgramDependencies, error) {
324-
if len(s.trackers) == 0 {
339+
if len(s.trackers) <= 1 {
325340
return nil,
326341
derived.NewProgramDependencies(),
327342
fmt.Errorf("cannot pop the programs dependency stack, because it is empty")
@@ -331,14 +346,11 @@ func (s *dependencyStack) pop() (common.Location, derived.ProgramDependencies, e
331346
tracker := s.trackers[len(s.trackers)-1]
332347
s.trackers = s.trackers[:len(s.trackers)-1]
333348

334-
// there are more trackers in the stack.
335-
// add the dependencies of the popped tracker to the parent tracker
349+
// Add the dependencies of the popped tracker to the parent tracker
336350
// This is an optimisation to avoid having to iterate through the entire stack
337351
// everytime a dependency is pushed or added, instead we add the popped dependencies to the new top of the stack.
338352
// (because if C depends on B which depends on A, A's dependencies include C).
339-
if len(s.trackers) > 0 {
340-
s.trackers[len(s.trackers)-1].dependencies.Merge(tracker.dependencies)
341-
}
353+
s.trackers[len(s.trackers)-1].dependencies.Merge(tracker.dependencies)
342354

343355
return tracker.location, tracker.dependencies, nil
344356
}

0 commit comments

Comments
 (0)