From 9b1d89c56897cc5193ad4b3bb2663aeca26502ec Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Tue, 23 Jul 2024 12:27:39 +0300 Subject: [PATCH 1/7] Add support for EVM heartbeat() method on system chunk transaction --- emulator/blockchain.go | 2 ++ .../systemChunkTransactionTemplate.cdc | 8 ++++++ server/access/streamBackend.go | 25 +++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/emulator/blockchain.go b/emulator/blockchain.go index 4214603b..c0f2c650 100644 --- a/emulator/blockchain.go +++ b/emulator/blockchain.go @@ -1801,6 +1801,8 @@ func (b *Blockchain) systemChunkTransaction() (*flowgo.TransactionBody, error) { RandomBeaconHistoryAddress: b.GetChain().ServiceAddress().Hex(), }, ) + // We should move this to `templates.Environment` struct + script = strings.ReplaceAll(script, "\"EVM\"", b.GetChain().ServiceAddress().HexWithPrefix()) tx := flowgo.NewTransactionBody(). SetScript([]byte(script)). diff --git a/emulator/templates/systemChunkTransactionTemplate.cdc b/emulator/templates/systemChunkTransactionTemplate.cdc index 4a980dde..c22c04b6 100644 --- a/emulator/templates/systemChunkTransactionTemplate.cdc +++ b/emulator/templates/systemChunkTransactionTemplate.cdc @@ -1,4 +1,5 @@ import RandomBeaconHistory from "RandomBeaconHistory" +import EVM from "EVM" transaction { prepare(serviceAccount: auth(BorrowValue) &Account) { @@ -6,5 +7,12 @@ transaction { .borrow<&RandomBeaconHistory.Heartbeat>(from: RandomBeaconHistory.HeartbeatStoragePath) ?? panic("Couldn't borrow RandomBeaconHistory.Heartbeat Resource") randomBeaconHistoryHeartbeat.heartbeat(randomSourceHistory: randomSourceHistory()) + + let evmHeartbeat = serviceAccount.storage.borrow<&EVM.Heartbeat>(from: /storage/EVMHeartbeat) + if evmHeartbeat != nil { // skip if not available + evmHeartbeat!.heartbeat() + } else { + panic("Couldn't borrow EVM.Heartbeat Resource") + } } } diff --git a/server/access/streamBackend.go b/server/access/streamBackend.go index cffffb95..8b27f633 100644 --- a/server/access/streamBackend.go +++ b/server/access/streamBackend.go @@ -28,6 +28,7 @@ import ( "github.com/onflow/flow-go/engine/access/state_stream/backend" "github.com/onflow/flow-go/engine/access/subscription" "github.com/onflow/flow-go/engine/common/rpc" + evmTypes "github.com/onflow/flow-go/fvm/evm/types" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/executiondatasync/execution_data" "github.com/onflow/flow-go/storage" @@ -196,6 +197,30 @@ func getExecutionDataFunc(blockchain *emulator.Blockchain) GetExecutionDataFunc chunks[i] = chunk } + // The `EVM.BlockExecuted` event is only emitted from the + // system chunk transaction, and we need to make it available + // in the returned response. + evmBlockExecutedEventType := fmt.Sprintf( + "A.%s.%s", + blockchain.GetChain().ServiceAddress().Hex(), + string(evmTypes.EventTypeBlockExecuted), + ) + events, err := blockchain.GetEventsByHeight( + height, + evmBlockExecutedEventType, + ) + if err != nil { + return nil, err + } + // Add the `EVM.BlockExecuted` event to the events of the last + // chunk. + if len(chunks) > 0 { + lastChunk := chunks[len(chunks)-1] + for _, event := range events { + lastChunk.Events = append(lastChunk.Events, event) + } + } + executionData := &execution_data.BlockExecutionData{ BlockID: block.ID(), ChunkExecutionDatas: chunks, From b0cf603f675dc89912303553bc198f1cd1f17026 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Tue, 23 Jul 2024 16:07:13 +0300 Subject: [PATCH 2/7] Temporariry disable block commitment on Cadence 1.0 migration test case --- storage/migration/cadence1_test.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/storage/migration/cadence1_test.go b/storage/migration/cadence1_test.go index 7acbbbcc..621f6450 100644 --- a/storage/migration/cadence1_test.go +++ b/storage/migration/cadence1_test.go @@ -572,11 +572,15 @@ func TestLoadMigratedValuesInTransaction(t *testing.T) { result.Logs, ) - _, err = blockchain.CommitBlock() - require.NoError(t, err) + // TEMP: Disable for now, as block commitment requires + // the EVM contract to be deployed. The system chunk + // transaction is calling the EVM.Heartbeat.heartbeat() + // method, to advance the EVM blocks. + // _, err = blockchain.CommitBlock() + // require.NoError(t, err) // tx status becomes TransactionStatusSealed - tx1Result, err := adapter.GetTransactionResult(context.Background(), tx.ID()) - require.NoError(t, err) - require.Equal(t, flowsdk.TransactionStatusSealed, tx1Result.Status) + // tx1Result, err := adapter.GetTransactionResult(context.Background(), tx.ID()) + // require.NoError(t, err) + // require.Equal(t, flowsdk.TransactionStatusSealed, tx1Result.Status) } From 65686db3250091aa55f3ebe05ba60889c1b67fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Tue, 23 Jul 2024 09:40:09 -0700 Subject: [PATCH 3/7] improve borrowing of EVM heartbeat --- emulator/templates/systemChunkTransactionTemplate.cdc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/emulator/templates/systemChunkTransactionTemplate.cdc b/emulator/templates/systemChunkTransactionTemplate.cdc index c22c04b6..ef714ed2 100644 --- a/emulator/templates/systemChunkTransactionTemplate.cdc +++ b/emulator/templates/systemChunkTransactionTemplate.cdc @@ -8,11 +8,9 @@ transaction { ?? panic("Couldn't borrow RandomBeaconHistory.Heartbeat Resource") randomBeaconHistoryHeartbeat.heartbeat(randomSourceHistory: randomSourceHistory()) - let evmHeartbeat = serviceAccount.storage.borrow<&EVM.Heartbeat>(from: /storage/EVMHeartbeat) - if evmHeartbeat != nil { // skip if not available - evmHeartbeat!.heartbeat() - } else { - panic("Couldn't borrow EVM.Heartbeat Resource") - } + let evmHeartbeat = serviceAccount.storage + .borrow<&EVM.Heartbeat>(from: /storage/EVMHeartbeat) + ?? panic("Couldn't borrow EVM.Heartbeat Resource") + evmHeartbeat.heartbeat() } } From c29da6bacee36cfe35b59c71836346320f9befb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Tue, 23 Jul 2024 09:40:43 -0700 Subject: [PATCH 4/7] use address location type ID construction instead of manual type ID formatting --- server/access/streamBackend.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/access/streamBackend.go b/server/access/streamBackend.go index 8b27f633..c30caa02 100644 --- a/server/access/streamBackend.go +++ b/server/access/streamBackend.go @@ -24,6 +24,7 @@ import ( "fmt" "time" + "github.com/onflow/cadence/runtime/common" "github.com/onflow/flow-go/engine/access/state_stream" "github.com/onflow/flow-go/engine/access/state_stream/backend" "github.com/onflow/flow-go/engine/access/subscription" @@ -200,14 +201,13 @@ func getExecutionDataFunc(blockchain *emulator.Blockchain) GetExecutionDataFunc // The `EVM.BlockExecuted` event is only emitted from the // system chunk transaction, and we need to make it available // in the returned response. - evmBlockExecutedEventType := fmt.Sprintf( - "A.%s.%s", - blockchain.GetChain().ServiceAddress().Hex(), - string(evmTypes.EventTypeBlockExecuted), - ) + evmBlockExecutedEventType := common.AddressLocation{ + Address: common.Address(blockchain.GetChain().ServiceAddress()), + Name: string(evmTypes.EventTypeBlockExecuted), + } events, err := blockchain.GetEventsByHeight( height, - evmBlockExecutedEventType, + evmBlockExecutedEventType.ID(), ) if err != nil { return nil, err From 8b39b782f2d8f6010fe7ae722de5d58ace850a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Tue, 23 Jul 2024 15:37:49 -0700 Subject: [PATCH 5/7] fix Cadence 1.0 migration and bring back test the pre-1.0 Emulator state does not contain the EVM contract, so deploy it. This must be done by deploying the minimal contract and updating to the full contract, as deploying the full contract is only possible during bootstrapping --- storage/migration/cadence1_test.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/storage/migration/cadence1_test.go b/storage/migration/cadence1_test.go index 621f6450..d7aa8f96 100644 --- a/storage/migration/cadence1_test.go +++ b/storage/migration/cadence1_test.go @@ -94,7 +94,7 @@ func migrateEmulatorState(t *testing.T, store *sqlite.Store) { err := MigrateCadence1( store, t.TempDir(), - migrations.EVMContractChangeNone, + migrations.EVMContractChangeDeployMinimalAndUpdateFull, migrations.BurnerContractChangeDeploy, stagedContracts, rwf, @@ -572,15 +572,11 @@ func TestLoadMigratedValuesInTransaction(t *testing.T) { result.Logs, ) - // TEMP: Disable for now, as block commitment requires - // the EVM contract to be deployed. The system chunk - // transaction is calling the EVM.Heartbeat.heartbeat() - // method, to advance the EVM blocks. - // _, err = blockchain.CommitBlock() - // require.NoError(t, err) + _, err = blockchain.CommitBlock() + require.NoError(t, err) // tx status becomes TransactionStatusSealed - // tx1Result, err := adapter.GetTransactionResult(context.Background(), tx.ID()) - // require.NoError(t, err) - // require.Equal(t, flowsdk.TransactionStatusSealed, tx1Result.Status) + tx1Result, err := adapter.GetTransactionResult(context.Background(), tx.ID()) + require.NoError(t, err) + require.Equal(t, flowsdk.TransactionStatusSealed, tx1Result.Status) } From 4691a81067e67971555996ce7be3b903e739d75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 24 Jul 2024 15:30:22 -0700 Subject: [PATCH 6/7] type moved to different package --- server/access/streamBackend.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/access/streamBackend.go b/server/access/streamBackend.go index c30caa02..3f57418e 100644 --- a/server/access/streamBackend.go +++ b/server/access/streamBackend.go @@ -29,7 +29,7 @@ import ( "github.com/onflow/flow-go/engine/access/state_stream/backend" "github.com/onflow/flow-go/engine/access/subscription" "github.com/onflow/flow-go/engine/common/rpc" - evmTypes "github.com/onflow/flow-go/fvm/evm/types" + evmEvents "github.com/onflow/flow-go/fvm/evm/events" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/executiondatasync/execution_data" "github.com/onflow/flow-go/storage" @@ -203,8 +203,9 @@ func getExecutionDataFunc(blockchain *emulator.Blockchain) GetExecutionDataFunc // in the returned response. evmBlockExecutedEventType := common.AddressLocation{ Address: common.Address(blockchain.GetChain().ServiceAddress()), - Name: string(evmTypes.EventTypeBlockExecuted), + Name: string(evmEvents.EventTypeBlockExecuted), } + events, err := blockchain.GetEventsByHeight( height, evmBlockExecutedEventType.ID(), From fb4820d80e9cbb5a47215c89ac73575db1f1fa20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 24 Jul 2024 15:36:54 -0700 Subject: [PATCH 7/7] improve import replacement --- emulator/blockchain.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/emulator/blockchain.go b/emulator/blockchain.go index c0f2c650..0bc76d7d 100644 --- a/emulator/blockchain.go +++ b/emulator/blockchain.go @@ -1795,20 +1795,30 @@ func (b *Blockchain) GetSourceFile(location common.Location) string { } func (b *Blockchain) systemChunkTransaction() (*flowgo.TransactionBody, error) { + serviceAddress := b.GetChain().ServiceAddress() + script := templates.ReplaceAddresses( systemChunkTransactionTemplate, templates.Environment{ - RandomBeaconHistoryAddress: b.GetChain().ServiceAddress().Hex(), + RandomBeaconHistoryAddress: serviceAddress.Hex(), }, ) - // We should move this to `templates.Environment` struct - script = strings.ReplaceAll(script, "\"EVM\"", b.GetChain().ServiceAddress().HexWithPrefix()) + + // TODO: move this to `templates.Environment` struct + script = strings.ReplaceAll( + script, + `import EVM from "EVM"`, + fmt.Sprintf( + "import EVM from %s", + serviceAddress.HexWithPrefix(), + ), + ) tx := flowgo.NewTransactionBody(). SetScript([]byte(script)). SetComputeLimit(flowgo.DefaultMaxTransactionGasLimit). - AddAuthorizer(b.GetChain().ServiceAddress()). - SetPayer(b.GetChain().ServiceAddress()). + AddAuthorizer(serviceAddress). + SetPayer(serviceAddress). SetReferenceBlockID(b.pendingBlock.parentID) return tx, nil