diff --git a/engine/access/rest/router/router.go b/engine/access/rest/router/router.go index 453b2874b93..009eb3681e3 100644 --- a/engine/access/rest/router/router.go +++ b/engine/access/rest/router/router.go @@ -70,6 +70,9 @@ func (b *RouterBuilder) AddRestRoutes( } // AddLegacyWebsocketsRoutes adds WebSocket routes to the router. +// +// Deprecated: Use AddWebsocketsRoute instead, which allows managing multiple streams with +// a single endpoint. func (b *RouterBuilder) AddLegacyWebsocketsRoutes( stateStreamApi state_stream.API, chain flow.Chain, diff --git a/engine/access/rest/websockets/handler.go b/engine/access/rest/websockets/handler.go index 8dbe13078ad..cb3ff467f65 100644 --- a/engine/access/rest/websockets/handler.go +++ b/engine/access/rest/websockets/handler.go @@ -38,8 +38,7 @@ func NewWebSocketHandler( } func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - //TODO: change to accept topic instead of URL - logger := h.HttpHandler.Logger.With().Str("websocket_subscribe_url", r.URL.String()).Logger() + logger := h.HttpHandler.Logger.With().Str("component", "websocket-handler").Logger() err := h.HttpHandler.VerifyRequest(w, r) if err != nil { diff --git a/engine/access/rest/websockets/legacy/websocket_handler.go b/engine/access/rest/websockets/legacy/websocket_handler.go index 1b09b958751..fba0a522eea 100644 --- a/engine/access/rest/websockets/legacy/websocket_handler.go +++ b/engine/access/rest/websockets/legacy/websocket_handler.go @@ -22,6 +22,8 @@ import ( // WebsocketController holds the necessary components and parameters for handling a WebSocket subscription. // It manages the communication between the server and the WebSocket client for subscribing. +// +// Deprecated: Use websockets.Controller which allows managing multiple subscriptions with a single connection. type WebsocketController struct { logger zerolog.Logger conn *websocket.Conn // the WebSocket connection for communication with the client diff --git a/fvm/environment/derived_data_invalidator_test.go b/fvm/environment/derived_data_invalidator_test.go index 147c03fb57a..9598d93f4b1 100644 --- a/fvm/environment/derived_data_invalidator_test.go +++ b/fvm/environment/derived_data_invalidator_test.go @@ -244,7 +244,7 @@ func TestMeterParamOverridesUpdated(t *testing.T) { snapshotTree := snapshot.NewSnapshotTree(nil) - ctx := fvm.NewContext(fvm.WithChain(flow.Testnet.Chain())) + ctx := fvm.NewContext(fvm.WithChain(flow.Emulator.Chain())) vm := fvm.NewVirtualMachine() executionSnapshot, _, err := vm.Run( diff --git a/fvm/executionParameters.go b/fvm/executionParameters.go index 5d4fd4febdd..48b28d6c2af 100644 --- a/fvm/executionParameters.go +++ b/fvm/executionParameters.go @@ -19,6 +19,7 @@ import ( "github.com/onflow/flow-go/fvm/storage" "github.com/onflow/flow-go/fvm/storage/derived" "github.com/onflow/flow-go/fvm/storage/state" + "github.com/onflow/flow-go/fvm/systemcontracts" ) func ProcedureStateParameters( @@ -143,10 +144,14 @@ func (computer ExecutionParametersComputer) getExecutionParameters() ( derived.StateExecutionParameters, error, ) { - // Check that the service account exists because all the settings are - // stored in it - serviceAddress := computer.ctx.Chain.ServiceAddress() - service := common.Address(serviceAddress) + sc := systemcontracts.SystemContractsForChain(computer.ctx.Chain.ChainID()) + + // The execution parameters are stored in the ExecutionParametersAccount. This is + // just the service account for all networks except mainnet and testnet. + // For mainnet and testnet, the execution parameters are stored in a separate + // account, so that they are separated from the frequently changing data on the + // service account. + service := common.Address(sc.ExecutionParametersAccount.Address) env := environment.NewScriptEnv( context.Background(), diff --git a/fvm/fvm_test.go b/fvm/fvm_test.go index eaa8bef6c85..503b9fb5cc7 100644 --- a/fvm/fvm_test.go +++ b/fvm/fvm_test.go @@ -1083,7 +1083,11 @@ func TestTransactionFeeDeduction(t *testing.T) { func TestSettingExecutionWeights(t *testing.T) { + // change the chain so that the metering settings are read from the service account + chain := flow.Emulator.Chain() + t.Run("transaction should fail with high weights", newVMTest().withBootstrapProcedureOptions( + fvm.WithMinimumStorageReservation(fvm.DefaultMinimumStorageReservation), fvm.WithAccountCreationFee(fvm.DefaultAccountCreationFee), fvm.WithStorageMBPerFLOW(fvm.DefaultStorageMBPerFLOW), @@ -1092,6 +1096,8 @@ func TestSettingExecutionWeights(t *testing.T) { common.ComputationKindLoop: 100_000 << meter.MeterExecutionInternalPrecisionBytes, }, ), + ).withContextOptions( + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { @@ -1140,6 +1146,7 @@ func TestSettingExecutionWeights(t *testing.T) { ), ).withContextOptions( fvm.WithMemoryLimit(10_000_000_000), + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { // Create an account private key. @@ -1190,6 +1197,7 @@ func TestSettingExecutionWeights(t *testing.T) { ), ).withContextOptions( fvm.WithMemoryLimit(10_000_000_000), + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { @@ -1234,6 +1242,8 @@ func TestSettingExecutionWeights(t *testing.T) { fvm.WithExecutionMemoryWeights( memoryWeights, ), + ).withContextOptions( + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { privateKeys, err := testutil.GenerateAccountPrivateKeys(1) @@ -1301,6 +1311,8 @@ func TestSettingExecutionWeights(t *testing.T) { environment.ComputationKindCreateAccount: (fvm.DefaultComputationLimit + 1) << meter.MeterExecutionInternalPrecisionBytes, }, ), + ).withContextOptions( + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { txBody := flow.NewTransactionBody(). @@ -1337,6 +1349,8 @@ func TestSettingExecutionWeights(t *testing.T) { environment.ComputationKindCreateAccount: 100_000_000 << meter.MeterExecutionInternalPrecisionBytes, }, ), + ).withContextOptions( + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { @@ -1374,6 +1388,8 @@ func TestSettingExecutionWeights(t *testing.T) { environment.ComputationKindCreateAccount: 100_000_000 << meter.MeterExecutionInternalPrecisionBytes, }, ), + ).withContextOptions( + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { txBody := flow.NewTransactionBody(). @@ -1417,6 +1433,7 @@ func TestSettingExecutionWeights(t *testing.T) { fvm.WithAccountStorageLimit(true), fvm.WithTransactionFeesEnabled(true), fvm.WithMemoryLimit(math.MaxUint64), + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { // Use the maximum amount of computation so that the transaction still passes. @@ -1510,6 +1527,7 @@ func TestSettingExecutionWeights(t *testing.T) { fvm.WithAccountStorageLimit(true), fvm.WithTransactionFeesEnabled(true), fvm.WithMemoryLimit(math.MaxUint64), + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { // Create an account private key. @@ -2165,6 +2183,8 @@ func TestScriptExecutionLimit(t *testing.T) { t.Parallel() + chain := flow.Emulator.Chain() + script := fvm.Script([]byte(` access(all) fun main() { var s: Int256 = 1024102410241024 @@ -2206,6 +2226,7 @@ func TestScriptExecutionLimit(t *testing.T) { fvm.WithTransactionFeesEnabled(true), fvm.WithAccountStorageLimit(true), fvm.WithComputationLimit(10000), + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { scriptCtx := fvm.NewContextFromParent(ctx) @@ -2228,6 +2249,7 @@ func TestScriptExecutionLimit(t *testing.T) { fvm.WithTransactionFeesEnabled(true), fvm.WithAccountStorageLimit(true), fvm.WithComputationLimit(20000), + fvm.WithChain(chain), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { scriptCtx := fvm.NewContextFromParent(ctx) diff --git a/fvm/systemcontracts/system_contracts.go b/fvm/systemcontracts/system_contracts.go index 3760044698e..775649c565c 100644 --- a/fvm/systemcontracts/system_contracts.go +++ b/fvm/systemcontracts/system_contracts.go @@ -47,6 +47,10 @@ const ( // AccountNameEVMStorage is not a contract, but a special account that is used to store EVM state AccountNameEVMStorage = "EVMStorageAccount" + // AccountNameExecutionParametersAccount is not a contract, but a special account that is used to store execution parameters + // This is generally just the service account. For mainnet and testnet, it is a separate account, + // in order to separate it away from the frequently changing data on the service account. + AccountNameExecutionParametersAccount = "ExecutionParametersAccount" // Unqualified names of service events (not including address prefix or contract name) @@ -100,6 +104,11 @@ var ( evmStorageAddressTestnet = flow.HexToAddress("1a54ed2be7552821") // evmStorageAddressMainnet is the address of the EVM state storage contract on Mainnet evmStorageAddressMainnet = flow.HexToAddress("d421a63faae318f9") + + // executionParametersAddressTestnet is the address of the Execution Parameters contract on Testnet + executionParametersAddressTestnet = flow.HexToAddress("6997a2f2cf57b73a") + // executionParametersAddressMainnet is the address of the Execution Parameters contract on Mainnet + executionParametersAddressMainnet = flow.HexToAddress("f426ff57ee8f6110") ) // SystemContract represents a system contract on a particular chain. @@ -149,10 +158,11 @@ type SystemContracts struct { DKG SystemContract // service account related contracts - FlowServiceAccount SystemContract - NodeVersionBeacon SystemContract - RandomBeaconHistory SystemContract - FlowStorageFees SystemContract + FlowServiceAccount SystemContract + NodeVersionBeacon SystemContract + RandomBeaconHistory SystemContract + FlowStorageFees SystemContract + ExecutionParametersAccount SystemContract // token related contracts FlowFees SystemContract @@ -344,16 +354,28 @@ func init() { } } + executionParametersAccountFunc := func(chain flow.ChainID) flow.Address { + switch chain { + case flow.Mainnet: + return executionParametersAddressMainnet + case flow.Testnet: + return executionParametersAddressTestnet + default: + return serviceAddressFunc(chain) + } + } + contractAddressFunc = map[string]func(id flow.ChainID) flow.Address{ ContractNameIDTableStaking: epochAddressFunc, ContractNameEpoch: epochAddressFunc, ContractNameClusterQC: epochAddressFunc, ContractNameDKG: epochAddressFunc, - ContractNameNodeVersionBeacon: serviceAddressFunc, - ContractNameRandomBeaconHistory: serviceAddressFunc, - ContractNameServiceAccount: serviceAddressFunc, - ContractNameStorageFees: serviceAddressFunc, + ContractNameNodeVersionBeacon: serviceAddressFunc, + ContractNameRandomBeaconHistory: serviceAddressFunc, + ContractNameServiceAccount: serviceAddressFunc, + ContractNameStorageFees: serviceAddressFunc, + AccountNameExecutionParametersAccount: executionParametersAccountFunc, ContractNameFlowFees: nthAddressFunc(FlowFeesAccountIndex), ContractNameFungibleToken: nthAddressFunc(FungibleTokenAccountIndex), @@ -406,10 +428,11 @@ func init() { ClusterQC: addressOfContract(ContractNameClusterQC), DKG: addressOfContract(ContractNameDKG), - FlowServiceAccount: addressOfContract(ContractNameServiceAccount), - NodeVersionBeacon: addressOfContract(ContractNameNodeVersionBeacon), - RandomBeaconHistory: addressOfContract(ContractNameRandomBeaconHistory), - FlowStorageFees: addressOfContract(ContractNameStorageFees), + FlowServiceAccount: addressOfContract(ContractNameServiceAccount), + NodeVersionBeacon: addressOfContract(ContractNameNodeVersionBeacon), + RandomBeaconHistory: addressOfContract(ContractNameRandomBeaconHistory), + FlowStorageFees: addressOfContract(ContractNameStorageFees), + ExecutionParametersAccount: addressOfContract(AccountNameExecutionParametersAccount), FlowFees: addressOfContract(ContractNameFlowFees), FlowToken: addressOfContract(ContractNameFlowToken),