Skip to content

Commit

Permalink
Merge branch 'master' of github.com:onflow/cadence into issue1137
Browse files Browse the repository at this point in the history
  • Loading branch information
dsainati1 committed Nov 5, 2021
2 parents a83cd3f + b947b91 commit a86f1ab
Show file tree
Hide file tree
Showing 12 changed files with 1,903 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/tutorial/06-marketplace-compose.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ pub contract Marketplace {
// The fungible token vault of the owner of this sale.
// When someone buys a token, this resource can deposit
// tokens into their account.
access(account) let ownerVault: Capability<&AnyResource{FungibleToken.Receiver}>
pub let ownerVault: Capability<&AnyResource{FungibleToken.Receiver}>
init (vault: Capability<&AnyResource{FungibleToken.Receiver}>) {
self.forSale <- {}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/go-test/deep v1.0.5
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381
github.com/onflow/atree v0.1.0-beta1.0.20211027184039-559ee654ece9
github.com/opentracing/opentracing-go v1.2.0
github.com/rivo/uniseg v0.2.0
github.com/schollz/progressbar/v3 v3.8.3
github.com/stretchr/testify v1.7.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2Em
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/onflow/atree v0.1.0-beta1.0.20211027184039-559ee654ece9 h1:Da0Sm2gyZ3Z2UAVlXikXZ0gbDpujuDs9qG+lnaTgZEg=
github.com/onflow/atree v0.1.0-beta1.0.20211027184039-559ee654ece9/go.mod h1:+6x071HgCF/0v5hQcaE5qqjc2UqN5gCU8h5Mk6uqpOg=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk=
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
4 changes: 4 additions & 0 deletions runtime/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ package runtime
import (
"time"

opentracing "github.com/opentracing/opentracing-go"

"github.com/onflow/atree"

"github.com/onflow/cadence"
Expand Down Expand Up @@ -121,6 +123,8 @@ type Interface interface {
ValidatePublicKey(key *PublicKey) (bool, error)
// GetAccountContractNames returns the names of all contracts deployed in an account.
GetAccountContractNames(address Address) ([]string, error)
// RecordTrace records a opentracing trace
RecordTrace(operation string, location common.Location, duration time.Duration, logs []opentracing.LogRecord)
}

type Metrics interface {
Expand Down
44 changes: 44 additions & 0 deletions runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import (
"fmt"
"math"
goRuntime "runtime"
"time"

"github.com/onflow/atree"
"github.com/opentracing/opentracing-go"

"github.com/onflow/cadence/runtime/ast"
"github.com/onflow/cadence/runtime/common"
Expand Down Expand Up @@ -114,6 +116,14 @@ type OnInvokedFunctionReturnFunc func(
line int,
)

// OnRecordTraceFunc is a function thats records a trace.
type OnRecordTraceFunc func(
inter *Interpreter,
operationName string,
duration time.Duration,
logs []opentracing.LogRecord,
)

// InjectedCompositeFieldsHandlerFunc is a function that handles storage reads.
//
type InjectedCompositeFieldsHandlerFunc func(
Expand Down Expand Up @@ -257,6 +267,7 @@ type Interpreter struct {
onLoopIteration OnLoopIterationFunc
onFunctionInvocation OnFunctionInvocationFunc
onInvokedFunctionReturn OnInvokedFunctionReturnFunc
onRecordTrace OnRecordTraceFunc
injectedCompositeFieldsHandler InjectedCompositeFieldsHandlerFunc
contractValueHandler ContractValueHandlerFunc
importLocationHandler ImportLocationHandlerFunc
Expand All @@ -270,6 +281,7 @@ type Interpreter struct {
statement ast.Statement
atreeValueValidationEnabled bool
atreeStorageValidationEnabled bool
tracingEnabled bool
}

type Option func(*Interpreter) error
Expand Down Expand Up @@ -324,6 +336,16 @@ func WithOnInvokedFunctionReturnHandler(handler OnInvokedFunctionReturnFunc) Opt
}
}

// WithOnRecordTraceHandler returns an interpreter option which sets
// the given function as the on record trace function handler.
//
func WithOnRecordTraceHandler(handler OnRecordTraceFunc) Option {
return func(interpreter *Interpreter) error {
interpreter.SetOnRecordTraceHandler(handler)
return nil
}
}

// WithPredeclaredValues returns an interpreter option which declares
// the given the predeclared values.
//
Expand Down Expand Up @@ -475,6 +497,16 @@ func WithAtreeStorageValidationEnabled(enabled bool) Option {
}
}

// WithTracingEnabled returns an interpreter option which sets
// the tracing option.
//
func WithTracingEnabled(enabled bool) Option {
return func(interpreter *Interpreter) error {
interpreter.SetTracingEnabled(enabled)
return nil
}
}

// withTypeCodes returns an interpreter option which sets the type codes.
//
func withTypeCodes(typeCodes TypeCodes) Option {
Expand Down Expand Up @@ -562,6 +594,12 @@ func (interpreter *Interpreter) SetOnInvokedFunctionReturnHandler(function OnInv
interpreter.onInvokedFunctionReturn = function
}

// SetOnRecordTraceHandler sets the function that is triggered when an record trace is called.
//
func (interpreter *Interpreter) SetOnRecordTraceHandler(function OnRecordTraceFunc) {
interpreter.onRecordTrace = function
}

// SetStorage sets the value that is used for storage operations.
func (interpreter *Interpreter) SetStorage(storage Storage) {
interpreter.Storage = storage
Expand Down Expand Up @@ -646,6 +684,12 @@ func (interpreter *Interpreter) SetAtreeStorageValidationEnabled(enabled bool) {
interpreter.atreeStorageValidationEnabled = enabled
}

// SetTracingEnabled sets the tracing option.
//
func (interpreter *Interpreter) SetTracingEnabled(enabled bool) {
interpreter.tracingEnabled = enabled
}

// setTypeCodes sets the type codes.
//
func (interpreter *Interpreter) setTypeCodes(typeCodes TypeCodes) {
Expand Down
11 changes: 10 additions & 1 deletion runtime/interpreter/interpreter_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package interpreter

import (
"math/big"
"time"

"github.com/onflow/cadence/fixedpoint"
"github.com/onflow/cadence/runtime/ast"
Expand Down Expand Up @@ -526,6 +527,15 @@ func (interpreter *Interpreter) VisitConditionalExpression(expression *ast.Condi
}

func (interpreter *Interpreter) VisitInvocationExpression(invocationExpression *ast.InvocationExpression) ast.Repr {

// tracing
if interpreter.tracingEnabled {
startTime := time.Now()
defer func() {
interpreter.reportFunctionTrace(invocationExpression.InvokedExpression.String(), time.Since(startTime))
}()
}

// interpret the invoked expression
result := interpreter.evalExpression(invocationExpression.InvokedExpression)

Expand Down Expand Up @@ -591,7 +601,6 @@ func (interpreter *Interpreter) VisitInvocationExpression(invocationExpression *

// If this is invocation is optional chaining, wrap the result
// as an optional, as the result is expected to be an optional

if isOptionalChaining {
resultValue = NewSomeValueNonCopying(resultValue)
}
Expand Down
10 changes: 10 additions & 0 deletions runtime/interpreter/interpreter_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package interpreter

import (
"sort"
"time"

"github.com/onflow/cadence/runtime/ast"
"github.com/onflow/cadence/runtime/sema"
Expand All @@ -38,6 +39,14 @@ func (interpreter *Interpreter) VisitImportDeclaration(declaration *ast.ImportDe

func (interpreter *Interpreter) importResolvedLocation(resolvedLocation sema.ResolvedLocation) {

// tracing
if interpreter.tracingEnabled {
startTime := time.Now()
defer func() {
interpreter.reportImportTrace(resolvedLocation.Location.String(), time.Since(startTime))
}()
}

subInterpreter := interpreter.EnsureLoaded(resolvedLocation.Location)

// determine which identifiers are imported /
Expand Down Expand Up @@ -81,4 +90,5 @@ func (interpreter *Interpreter) importResolvedLocation(resolvedLocation sema.Res
interpreter.setVariable(name, variable)
interpreter.Globals.Set(name, variable)
}

}
68 changes: 68 additions & 0 deletions runtime/interpreter/interpreter_tracing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright 2019-2020 Dapper Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package interpreter

import (
"time"

"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/log"
)

const (
tracingFunctionPrefix = "function."
tracingImportPrefix = "import."
tracingArrayPrefix = "array."
tracingDictionaryPrefix = "dictionary."
tracingTransferPrefix = "transfer."
)

func (interpreter *Interpreter) reportFunctionTrace(functionName string, duration time.Duration) {
interpreter.onRecordTrace(interpreter, tracingFunctionPrefix+functionName, duration, nil)
}

func (interpreter *Interpreter) reportImportTrace(importPath string, duration time.Duration) {
interpreter.onRecordTrace(interpreter, tracingImportPrefix+importPath, duration, nil)
}

func (interpreter *Interpreter) reportArrayValueTransferTrace(typeInfo string, count int, duration time.Duration) {
logs := []opentracing.LogRecord{
{
Timestamp: time.Now(),
Fields: []log.Field{
log.Int("count", count),
log.String("type", typeInfo),
},
},
}
interpreter.onRecordTrace(interpreter, tracingArrayPrefix+tracingTransferPrefix, duration, logs)
}

func (interpreter *Interpreter) reportDictionaryValueTransferTrace(typeInfo string, count int, duration time.Duration) {
logs := []opentracing.LogRecord{
{
Timestamp: time.Now(),
Fields: []log.Field{
log.Int("count", count),
log.String("type", typeInfo),
},
},
}
interpreter.onRecordTrace(interpreter, tracingDictionaryPrefix+tracingTransferPrefix, duration, logs)
}
15 changes: 15 additions & 0 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"math"
"math/big"
"strings"
"time"

"github.com/onflow/atree"
"github.com/rivo/uniseg"
Expand Down Expand Up @@ -1479,6 +1480,13 @@ func (v *ArrayValue) Transfer(
storable atree.Storable,
) Value {

if interpreter.tracingEnabled {
startTime := time.Now()
defer func() {
interpreter.reportArrayValueTransferTrace(v.Type.String(), v.Count(), time.Since(startTime))
}()
}

array := v.array

needsStoreTo := v.NeedsStoreTo(address)
Expand Down Expand Up @@ -9352,6 +9360,13 @@ func (v *DictionaryValue) Transfer(
storable atree.Storable,
) Value {

if interpreter.tracingEnabled {
startTime := time.Now()
defer func() {
interpreter.reportDictionaryValueTransferTrace(v.Type.String(), v.Count(), time.Since(startTime))
}()
}

dictionary := v.dictionary

needsStoreTo := v.NeedsStoreTo(address)
Expand Down
24 changes: 24 additions & 0 deletions runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
goRuntime "runtime"
"time"

opentracing "github.com/opentracing/opentracing-go"
"golang.org/x/crypto/sha3"

"github.com/onflow/cadence"
Expand Down Expand Up @@ -88,6 +89,9 @@ type Runtime interface {
// SetAtreeValidationEnabled configures if atree validation is enabled.
SetAtreeValidationEnabled(enabled bool)

// SetTracingEnabled configures if tracing is enabled.
SetTracingEnabled(enabled bool)

// ReadStored reads the value stored at the given path
//
ReadStored(address common.Address, path cadence.Path, context Context) (cadence.Value, error)
Expand Down Expand Up @@ -151,6 +155,7 @@ type interpreterRuntime struct {
coverageReport *CoverageReport
contractUpdateValidationEnabled bool
atreeValidationEnabled bool
tracingEnabled bool
}

type Option func(Runtime)
Expand All @@ -173,6 +178,15 @@ func WithAtreeValidationEnabled(enabled bool) Option {
}
}

// WithTracingEnabled returns a runtime option
// that configures if tracing is enabled.
//
func WithTracingEnabled(enabled bool) Option {
return func(runtime Runtime) {
runtime.SetTracingEnabled(enabled)
}
}

// NewInterpreterRuntime returns a interpreter-based version of the Flow runtime.
func NewInterpreterRuntime(options ...Option) Runtime {
runtime := &interpreterRuntime{}
Expand All @@ -194,6 +208,10 @@ func (r *interpreterRuntime) SetAtreeValidationEnabled(enabled bool) {
r.atreeValidationEnabled = enabled
}

func (r *interpreterRuntime) SetTracingEnabled(enabled bool) {
r.tracingEnabled = enabled
}

func (r *interpreterRuntime) ExecuteScript(script Script, context Context) (cadence.Value, error) {
context.InitializeCodesAndPrograms()

Expand Down Expand Up @@ -1175,6 +1193,12 @@ func (r *interpreterRuntime) newInterpreter(
)
},
),
interpreter.WithOnRecordTraceHandler(
func(intr *interpreter.Interpreter, functionName string, duration time.Duration, logs []opentracing.LogRecord) {
context.Interface.RecordTrace(functionName, intr.Location, duration, logs)
},
),
interpreter.WithTracingEnabled(r.tracingEnabled),
interpreter.WithAtreeValueValidationEnabled(r.atreeValidationEnabled),
// NOTE: ignore r.atreeValidationEnabled here,
// and disable storage validation after each value modification.
Expand Down
Loading

0 comments on commit a86f1ab

Please sign in to comment.