Skip to content

Commit

Permalink
Merge pull request #553 from onflow/sainati/legacy-deploy
Browse files Browse the repository at this point in the history
Add config option to allow upgrading legacy contracts
  • Loading branch information
dsainati1 authored Jan 26, 2024
2 parents 92e2ffc + 3c6d5f5 commit ce8332d
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 67 deletions.
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 |

## 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-M4
github.com/onflow/crypto v0.25.0
github.com/onflow/flow-core-contracts/lib/go/templates v0.15.1-0.20240125214229-b7a95136dd0d
github.com/onflow/flow-go v0.33.2-0.20240126002816-f0770a716d61
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1973,8 +1973,9 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onflow/atree v0.6.1-0.20230711151834-86040b30171f h1:Z8/PgTqOgOg02MTRpTBYO2k16FE6z4wEOtaC2WBR9Xo=
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-M4 h1:/nt3j7vpYDxuI0ghIgAJrb2R01ijvJYZLAkKt+zbpTY=
github.com/onflow/cadence v1.0.0-M4/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.20240125214229-b7a95136dd0d h1:Afcfk/9jAQZ1v5PLGdP68FG/0yPPM60fn9Eq8ChBGS0=
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

0 comments on commit ce8332d

Please sign in to comment.