Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add config option to allow upgrading legacy contracts #553

Merged
merged 7 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ and if you plan to run the emulator with Docker you must use the environment var
| `--start-block-height` | `FLOW_STARTBLOCKHEIGHT` | `0` | Start block height to use when starting the network using 'testnet' or 'mainnet' as the chain-id |
| `--evm-enabled` | `FLOW_EVMENABLED` | `false` | Enable evm support |

| `--legacy-upgrade` | `FLOW_LEGACYUPGRADE` | `false` | Enable upgrading of legacy contracts |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I need to do anything to get the docker flag here to work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, not quite sure what you mean here, how is this related to Docker?


## Running the emulator with the Flow CLI

The emulator is bundled with the [Flow CLI](https://docs.onflow.org/flow-cli), a command-line interface for working with Flow.
Expand Down
126 changes: 64 additions & 62 deletions cmd/emulator/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,41 +39,42 @@ import (
)

type Config struct {
Port int `default:"3569" flag:"port,p" info:"port to run RPC server"`
DebuggerPort int `default:"2345" flag:"debugger-port" info:"port to run the Debugger (Debug Adapter Protocol)"`
RestPort int `default:"8888" flag:"rest-port" info:"port to run the REST API"`
AdminPort int `default:"8080" flag:"admin-port" info:"port to run the admin API"`
Verbose bool `default:"false" flag:"verbose,v" info:"enable verbose logging"`
LogFormat string `default:"text" flag:"log-format" info:"logging output format. Valid values (text, JSON)"`
BlockTime time.Duration `flag:"block-time,b" info:"time between sealed blocks, e.g. '300ms', '-1.5h' or '2h45m'. Valid units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'"`
ServicePrivateKey string `flag:"service-priv-key" info:"service account private key"`
ServicePublicKey string `flag:"service-pub-key" info:"service account public key"`
ServiceKeySigAlgo string `default:"ECDSA_P256" flag:"service-sig-algo" info:"service account key signature algorithm"`
ServiceKeyHashAlgo string `default:"SHA3_256" flag:"service-hash-algo" info:"service account key hash algorithm"`
Init bool `default:"false" flag:"init" info:"whether to initialize a new account profile"`
GRPCDebug bool `default:"false" flag:"grpc-debug" info:"enable gRPC server reflection for debugging with grpc_cli"`
RESTDebug bool `default:"false" flag:"rest-debug" info:"enable REST API debugging output"`
Persist bool `default:"false" flag:"persist" info:"enable persistent storage"`
Snapshot bool `default:"false" flag:"snapshot" info:"enable snapshots for emulator"`
DBPath string `default:"./flowdb" flag:"dbpath" info:"path to database directory"`
SimpleAddresses bool `default:"false" flag:"simple-addresses" info:"use sequential addresses starting with 0x01"`
TokenSupply string `default:"1000000000.0" flag:"token-supply" info:"initial FLOW token supply"`
TransactionExpiry int `default:"10" flag:"transaction-expiry" info:"transaction expiry, measured in blocks"`
StorageLimitEnabled bool `default:"true" flag:"storage-limit" info:"enable account storage limit"`
StorageMBPerFLOW string `flag:"storage-per-flow" info:"the MB amount of storage capacity an account has per 1 FLOW token it has. e.g. '100.0'. The default is taken from the current version of flow-go"`
MinimumAccountBalance string `flag:"min-account-balance" info:"The minimum account balance of an account. This is also the cost of creating one account. e.g. '0.001'. The default is taken from the current version of flow-go"`
TransactionFeesEnabled bool `default:"false" flag:"transaction-fees" info:"enable transaction fees"`
TransactionMaxGasLimit int `default:"9999" flag:"transaction-max-gas-limit" info:"maximum gas limit for transactions"`
ScriptGasLimit int `default:"100000" flag:"script-gas-limit" info:"gas limit for scripts"`
Contracts bool `default:"false" flag:"contracts" info:"deploy common contracts when emulator starts"`
ContractRemovalEnabled bool `default:"true" flag:"contract-removal" info:"allow removal of already deployed contracts, used for updating during development"`
SkipTxValidation bool `default:"false" flag:"skip-tx-validation" info:"skip verification of transaction signatures and sequence numbers"`
Host string `default:"" flag:"host" info:"host to listen on for emulator GRPC/REST/Admin servers (default: all interfaces)"`
ChainID string `default:"emulator" flag:"chain-id" info:"chain to emulate for address generation. Valid values are: 'emulator', 'testnet', 'mainnet'"`
RedisURL string `default:"" flag:"redis-url" info:"redis-server URL for persisting redis storage backend ( redis://[[username:]password@]host[:port][/database] ) "`
SqliteURL string `default:"" flag:"sqlite-url" info:"sqlite db URL for persisting sqlite storage backend "`
CoverageReportingEnabled bool `default:"false" flag:"coverage-reporting" info:"enable Cadence code coverage reporting"`
EVMEnabled bool `default:"false" flag:"evm-enabled" info:"enable EVM support"`
Port int `default:"3569" flag:"port,p" info:"port to run RPC server"`
DebuggerPort int `default:"2345" flag:"debugger-port" info:"port to run the Debugger (Debug Adapter Protocol)"`
RestPort int `default:"8888" flag:"rest-port" info:"port to run the REST API"`
AdminPort int `default:"8080" flag:"admin-port" info:"port to run the admin API"`
Verbose bool `default:"false" flag:"verbose,v" info:"enable verbose logging"`
LogFormat string `default:"text" flag:"log-format" info:"logging output format. Valid values (text, JSON)"`
BlockTime time.Duration `flag:"block-time,b" info:"time between sealed blocks, e.g. '300ms', '-1.5h' or '2h45m'. Valid units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'"`
ServicePrivateKey string `flag:"service-priv-key" info:"service account private key"`
ServicePublicKey string `flag:"service-pub-key" info:"service account public key"`
ServiceKeySigAlgo string `default:"ECDSA_P256" flag:"service-sig-algo" info:"service account key signature algorithm"`
ServiceKeyHashAlgo string `default:"SHA3_256" flag:"service-hash-algo" info:"service account key hash algorithm"`
Init bool `default:"false" flag:"init" info:"whether to initialize a new account profile"`
GRPCDebug bool `default:"false" flag:"grpc-debug" info:"enable gRPC server reflection for debugging with grpc_cli"`
RESTDebug bool `default:"false" flag:"rest-debug" info:"enable REST API debugging output"`
Persist bool `default:"false" flag:"persist" info:"enable persistent storage"`
Snapshot bool `default:"false" flag:"snapshot" info:"enable snapshots for emulator"`
DBPath string `default:"./flowdb" flag:"dbpath" info:"path to database directory"`
SimpleAddresses bool `default:"false" flag:"simple-addresses" info:"use sequential addresses starting with 0x01"`
TokenSupply string `default:"1000000000.0" flag:"token-supply" info:"initial FLOW token supply"`
TransactionExpiry int `default:"10" flag:"transaction-expiry" info:"transaction expiry, measured in blocks"`
StorageLimitEnabled bool `default:"true" flag:"storage-limit" info:"enable account storage limit"`
StorageMBPerFLOW string `flag:"storage-per-flow" info:"the MB amount of storage capacity an account has per 1 FLOW token it has. e.g. '100.0'. The default is taken from the current version of flow-go"`
MinimumAccountBalance string `flag:"min-account-balance" info:"The minimum account balance of an account. This is also the cost of creating one account. e.g. '0.001'. The default is taken from the current version of flow-go"`
TransactionFeesEnabled bool `default:"false" flag:"transaction-fees" info:"enable transaction fees"`
TransactionMaxGasLimit int `default:"9999" flag:"transaction-max-gas-limit" info:"maximum gas limit for transactions"`
ScriptGasLimit int `default:"100000" flag:"script-gas-limit" info:"gas limit for scripts"`
Contracts bool `default:"false" flag:"contracts" info:"deploy common contracts when emulator starts"`
ContractRemovalEnabled bool `default:"true" flag:"contract-removal" info:"allow removal of already deployed contracts, used for updating during development"`
SkipTxValidation bool `default:"false" flag:"skip-tx-validation" info:"skip verification of transaction signatures and sequence numbers"`
Host string `default:"" flag:"host" info:"host to listen on for emulator GRPC/REST/Admin servers (default: all interfaces)"`
ChainID string `default:"emulator" flag:"chain-id" info:"chain to emulate for address generation. Valid values are: 'emulator', 'testnet', 'mainnet'"`
RedisURL string `default:"" flag:"redis-url" info:"redis-server URL for persisting redis storage backend ( redis://[[username:]password@]host[:port][/database] ) "`
SqliteURL string `default:"" flag:"sqlite-url" info:"sqlite db URL for persisting sqlite storage backend "`
CoverageReportingEnabled bool `default:"false" flag:"coverage-reporting" info:"enable Cadence code coverage reporting"`
LegacyContractUpgradeEnabled bool `default:"false" flag:"legacy-upgrade" info:"enable Cadence legacy contract upgrade"`
EVMEnabled bool `default:"false" flag:"evm-enabled" info:"enable EVM support"`
// todo temporarily disabled until remote register endpoint is re-enabled
// StartBlockHeight uint64 `default:"0" flag:"start-block-height" info:"block height to start the emulator at. only valid when forking Mainnet or Testnet"`
}
Expand Down Expand Up @@ -174,33 +175,34 @@ func Cmd(getServiceKey serviceKeyFunc) *cobra.Command {
RESTPort: conf.RestPort,
RESTDebug: conf.RESTDebug,
// TODO: allow headers to be parsed from environment
HTTPHeaders: nil,
BlockTime: conf.BlockTime,
ServicePublicKey: servicePublicKey,
ServicePrivateKey: servicePrivateKey,
ServiceKeySigAlgo: serviceKeySigAlgo,
ServiceKeyHashAlgo: serviceKeyHashAlgo,
Persist: conf.Persist,
Snapshot: conf.Snapshot,
DBPath: conf.DBPath,
GenesisTokenSupply: parseCadenceUFix64(conf.TokenSupply, "token-supply"),
TransactionMaxGasLimit: uint64(conf.TransactionMaxGasLimit),
ScriptGasLimit: uint64(conf.ScriptGasLimit),
TransactionExpiry: uint(conf.TransactionExpiry),
StorageLimitEnabled: conf.StorageLimitEnabled,
StorageMBPerFLOW: storageMBPerFLOW,
MinimumStorageReservation: minimumStorageReservation,
TransactionFeesEnabled: conf.TransactionFeesEnabled,
WithContracts: conf.Contracts,
SkipTransactionValidation: conf.SkipTxValidation,
SimpleAddressesEnabled: conf.SimpleAddresses,
Host: conf.Host,
ChainID: flowChainID,
RedisURL: conf.RedisURL,
ContractRemovalEnabled: conf.ContractRemovalEnabled,
SqliteURL: conf.SqliteURL,
CoverageReportingEnabled: conf.CoverageReportingEnabled,
EVMEnabled: conf.EVMEnabled,
HTTPHeaders: nil,
BlockTime: conf.BlockTime,
ServicePublicKey: servicePublicKey,
ServicePrivateKey: servicePrivateKey,
ServiceKeySigAlgo: serviceKeySigAlgo,
ServiceKeyHashAlgo: serviceKeyHashAlgo,
Persist: conf.Persist,
Snapshot: conf.Snapshot,
DBPath: conf.DBPath,
GenesisTokenSupply: parseCadenceUFix64(conf.TokenSupply, "token-supply"),
TransactionMaxGasLimit: uint64(conf.TransactionMaxGasLimit),
ScriptGasLimit: uint64(conf.ScriptGasLimit),
TransactionExpiry: uint(conf.TransactionExpiry),
StorageLimitEnabled: conf.StorageLimitEnabled,
StorageMBPerFLOW: storageMBPerFLOW,
MinimumStorageReservation: minimumStorageReservation,
TransactionFeesEnabled: conf.TransactionFeesEnabled,
WithContracts: conf.Contracts,
SkipTransactionValidation: conf.SkipTxValidation,
SimpleAddressesEnabled: conf.SimpleAddresses,
Host: conf.Host,
ChainID: flowChainID,
RedisURL: conf.RedisURL,
ContractRemovalEnabled: conf.ContractRemovalEnabled,
SqliteURL: conf.SqliteURL,
CoverageReportingEnabled: conf.CoverageReportingEnabled,
LegacyContractUpgradeEnabled: conf.LegacyContractUpgradeEnabled,
EVMEnabled: conf.EVMEnabled,
// todo temporarily disabled until remote register endpoint is re-enabled
// StartBlockHeight: conf.StartBlockHeight,
}
Expand Down
19 changes: 16 additions & 3 deletions emulator/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ func WithSimpleAddresses() Option {
}
}

// WithLegacyUpgradeEnabled enables parsing of old contracts for legacy upgrade purposes
func WithLegacyUpgradeEnabled() Option {
return func(c *config) {
c.LegacyContractUpgradeEnabled = true
}
}

// WithGenesisTokenSupply sets the genesis token supply.
func WithGenesisTokenSupply(supply cadence.UFix64) Option {
return func(c *config) {
Expand Down Expand Up @@ -358,6 +365,7 @@ type config struct {
StorageLimitEnabled bool
TransactionFeesEnabled bool
ContractRemovalEnabled bool
LegacyContractUpgradeEnabled bool
EVMEnabled bool
MinimumStorageReservation cadence.UFix64
StorageMBPerFLOW cadence.UFix64
Expand Down Expand Up @@ -471,6 +479,10 @@ func (b *Blockchain) Ping() error {
return nil
}

func (b *Blockchain) Runtime() runtime.Runtime {
return b.coverageReportedRuntime
}

func (b *Blockchain) GetChain() flowgo.Chain {
return b.vmCtx.Chain
}
Expand Down Expand Up @@ -579,9 +591,10 @@ func configureFVM(blockchain *Blockchain, conf config, blocks *blocks) (*fvm.Vir
cadenceLogger := conf.Logger.Hook(CadenceHook{MainLogger: &conf.ServerLogger}).Level(zerolog.DebugLevel)

runtimeConfig := runtime.Config{
Debugger: blockchain.debugger,
AttachmentsEnabled: true,
CoverageReport: conf.CoverageReport,
Debugger: blockchain.debugger,
AttachmentsEnabled: true,
LegacyContractUpgradeEnabled: conf.LegacyContractUpgradeEnabled,
CoverageReport: conf.CoverageReport,
}
coverageReportedRuntime := &CoverageReportedRuntime{
Runtime: runtime.NewInterpreterRuntime(runtimeConfig),
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/improbable-eng/grpc-web v0.15.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/onflow/cadence v1.0.0-M3
github.com/onflow/cadence v1.0.0-preview.2.0.20240124204828-3adb0330b148
dsainati1 marked this conversation as resolved.
Show resolved Hide resolved
github.com/onflow/crypto v0.25.0
github.com/onflow/flow-core-contracts/lib/go/templates v0.15.1-0.20240125013952-df76aaf4136f
github.com/onflow/flow-go v0.33.2-0.20240125033624-f3bd7a6004cf
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1975,6 +1975,8 @@ github.com/onflow/atree v0.6.1-0.20230711151834-86040b30171f h1:Z8/PgTqOgOg02MTR
github.com/onflow/atree v0.6.1-0.20230711151834-86040b30171f/go.mod h1:xvP61FoOs95K7IYdIYRnNcYQGf4nbF/uuJ0tHf4DRuM=
github.com/onflow/cadence v1.0.0-M3 h1:bSydJise9pU4aALloUKv/EWmDLITRlbBpuG8OPBydZM=
github.com/onflow/cadence v1.0.0-M3/go.mod h1:odXGZZ/wGNA5mwT8bC9v8u8EXACHllB2ABSZK65TGL8=
github.com/onflow/cadence v1.0.0-preview.2.0.20240124204828-3adb0330b148 h1:v1UFNLJXZinLQOLHgecrKAFaPB7zF92WZNxhtTfQlNM=
github.com/onflow/cadence v1.0.0-preview.2.0.20240124204828-3adb0330b148/go.mod h1:odXGZZ/wGNA5mwT8bC9v8u8EXACHllB2ABSZK65TGL8=
github.com/onflow/crypto v0.25.0 h1:BeWbLsh3ZD13Ej+Uky6kg1PL1ZIVBDVX+2MVBNwqddg=
github.com/onflow/crypto v0.25.0/go.mod h1:C8FbaX0x8y+FxWjbkHy0Q4EASCDR9bSPWZqlpCLYyVI=
github.com/onflow/flow-core-contracts/lib/go/contracts v0.15.1-0.20240125013952-df76aaf4136f h1:QXRSJn3RfmrMfhCiCzDLP5F4aDtoyN+jGuTb6CMBIEA=
Expand Down
9 changes: 9 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ type Config struct {
SqliteURL string
// CoverageReportingEnabled enables/disables Cadence code coverage reporting.
CoverageReportingEnabled bool
// LegacyUpgradeEnabled enables/disables Cadence legacy contracts upgrades
LegacyContractUpgradeEnabled bool
// StartBlockHeight is the height at which to start the emulator.
StartBlockHeight uint64
}
Expand Down Expand Up @@ -407,6 +409,13 @@ func configureBlockchain(logger *zerolog.Logger, conf *Config, store storage.Sto
)
}

if conf.LegacyContractUpgradeEnabled {
options = append(
options,
emulator.WithLegacyUpgradeEnabled(),
)
}

emulatedBlockchain, err := emulator.New(options...)
if err != nil {
return nil, err
Expand Down
17 changes: 17 additions & 0 deletions server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"os"
"testing"

"github.com/onflow/flow-emulator/emulator"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -79,6 +80,22 @@ func TestPersistenceWithSnapshotFlag(t *testing.T) {
require.True(t, os.IsNotExist(err), "DB should not exist")
}

func TestLegacyUpgradeFlag(t *testing.T) {
logger := zerolog.Nop()

conf := &Config{LegacyContractUpgradeEnabled: true}
server := NewEmulatorServer(&logger, conf)
defer server.Stop()

require.NotNil(t, server)
require.True(t, server.config.LegacyContractUpgradeEnabled)

e := server.Emulator()

require.IsType(t, &emulator.Blockchain{}, e)
require.True(t, e.(*emulator.Blockchain).Runtime().Config().LegacyContractUpgradeEnabled)
}

func TestExecuteScript(t *testing.T) {

logger := zerolog.Nop()
Expand Down