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 support for EVM.heartbeat resource on system chunk transaction #717

Merged
merged 8 commits into from
Jul 24, 2024
18 changes: 15 additions & 3 deletions emulator/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1795,18 +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(),
},
)

// 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
Expand Down
6 changes: 6 additions & 0 deletions emulator/templates/systemChunkTransactionTemplate.cdc
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import RandomBeaconHistory from "RandomBeaconHistory"
import EVM from "EVM"

transaction {
prepare(serviceAccount: auth(BorrowValue) &Account) {
let randomBeaconHistoryHeartbeat = serviceAccount.storage
.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)
?? panic("Couldn't borrow EVM.Heartbeat Resource")
evmHeartbeat.heartbeat()
}
}
26 changes: 26 additions & 0 deletions server/access/streamBackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ 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"
"github.com/onflow/flow-go/engine/common/rpc"
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"
Expand Down Expand Up @@ -196,6 +198,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 := common.AddressLocation{
Address: common.Address(blockchain.GetChain().ServiceAddress()),
Name: string(evmEvents.EventTypeBlockExecuted),
}

events, err := blockchain.GetEventsByHeight(
height,
evmBlockExecutedEventType.ID(),
)
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,
Expand Down
2 changes: 1 addition & 1 deletion storage/migration/cadence1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading