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

Feat/execution service #2098

Merged
merged 10 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 0 additions & 1 deletion committee/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ func (n *Node) submit(ctx context.Context, request db.SignRequest) error {
logger.Errorf("could not get submission status: %w", err)
}

fmt.Println("fuck")
fmt.Printf("tx hash: %s\n", yo.TxHash().String())
fmt.Printf("new signed hash: %s \n", request.SignedEntryHash.String())
fmt.Println("you")
Expand Down
83 changes: 83 additions & 0 deletions packages/contracts-communication/contracts/ExecutionService.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import {IExecutionService} from "./interfaces/IExecutionService.sol";
import {ExecutionServiceEvents} from "./events/ExecutionServiceEvents.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

import {IGasOracle} from "./interfaces/IGasOracle.sol";

import {OptionsLib, OptionsV1} from "./libs/Options.sol";

contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {
using OptionsLib for bytes;

address public interchainClient;
address public executorEOA;
IGasOracle public gasOracle;

constructor() Ownable(msg.sender) {}

function setInterchainClient(address _interchainClient) external onlyOwner {
interchainClient = _interchainClient;
emit InterchainClientUpdated(_interchainClient);
}

function setExecutorEOA(address _executorEOA) external onlyOwner {
executorEOA = _executorEOA;
emit ExecutorEOAUpdated(executorEOA);
}

function setGasOracle(address _gasOracle) external onlyOwner {
gasOracle = IGasOracle(_gasOracle);
emit GasOracleUpdated(_gasOracle);
}

modifier onlyInterchainClient() {
require(msg.sender == interchainClient, "ExecutionService: caller is not the InterchainClient");
_;
}

// @inheritdoc
function requestExecution(
uint256 dstChainId,
uint256 txPayloadSize,
bytes32 transactionId,
uint256 executionFee,
bytes memory options
)
external
override
onlyInterchainClient
{
require(
executionFee >= getExecutionFee(dstChainId, txPayloadSize, options),
"ExecutionService: execution fee is not high enough"
);
emit ExecutionRequested(transactionId);
}

// @inheritdoc
function getExecutionFee(
uint256 dstChainId,
uint256 txPayloadSize,
bytes memory options
)
public
view
override
returns (uint256)
{
(uint8 version, bytes memory data) = options.decodeVersionedOptions();
if (version == OptionsLib.OPTIONS_V1) {
OptionsV1 memory optionsV1 = options.decodeOptionsV1();
uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);
if (optionsV1.gasAirdrop > 0) {
baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);
}
return baseCost;
} else {
revert("Unsupported options version: version must be OPTIONS_V1");
}
}
}
5 changes: 4 additions & 1 deletion packages/contracts-communication/contracts/InterchainApp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ contract InterchainApp is IInterchainApp {

address[] private sendingModules;
address[] private receivingModules;
address private executionService;

struct AppConfig {
// ChainID -> Linked IApps
Expand All @@ -33,6 +34,7 @@ contract InterchainApp is IInterchainApp {
address[] memory linkedIApps,
address[] memory _sendingModules,
address[] memory _receivingModules,
address _executionService,
uint256 _requiredResponses,
uint64 _optimisticTimePeriod
)
Expand All @@ -50,6 +52,7 @@ contract InterchainApp is IInterchainApp {

localAppConfig.sendingModules = _sendingModules;
localAppConfig.receivingModules = _receivingModules;
executionService = _executionService;
}

// Getters for the application configuration
Expand Down Expand Up @@ -95,7 +98,7 @@ contract InterchainApp is IInterchainApp {
bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();
// TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this
interchain.interchainSend{value: msg.value}(
dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message
dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message
);
emit AppMessageSent();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract ExecutionServiceEvents {
event ExecutionRequested(bytes32 indexed transactionId);
event ExecutorEOAUpdated(address indexed executorEOA);
event GasOracleUpdated(address indexed gasOracle);
event InterchainClientUpdated(address indexed interchainClient);
}
4 changes: 2 additions & 2 deletions packages/contracts-communication/script/MessagingBase.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ contract MessagingBase is Script {
uint256 _requiredResponses = 1;
uint64 _optimisticTimePeriod = 1;
icApp.setAppConfig(
chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod
chainIDs, linkedIApps, _sendingModules, _receivingModules, address(0), _requiredResponses, _optimisticTimePeriod
);
vm.stopBroadcast();
}
Expand All @@ -84,7 +84,7 @@ contract MessagingBase is Script {
uint256 _requiredResponses = 1;
uint64 _optimisticTimePeriod = 1;
icApp.setAppConfig(
chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod
chainIDs, linkedIApps, _sendingModules, _receivingModules, address(0), _requiredResponses, _optimisticTimePeriod
);
vm.stopBroadcast();
}
Expand Down
22 changes: 22 additions & 0 deletions packages/contracts-communication/test/ExecutionService.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import {ExecutionService, ExecutionServiceEvents, IExecutionService} from "../contracts/ExecutionService.sol";
import {Test} from "forge-std/Test.sol";
import {GasOracleMock} from "./mocks/GasOracleMock.sol";

contract ExecutionServiceTest is ExecutionServiceEvents, Test {
ExecutionService public executionService;
GasOracleMock public gasOracle;

address icClient = address(0x123);
address executorEOA = address(0x456);

function setUp() public {
gasOracle = new GasOracleMock();
executionService = new ExecutionService();
executionService.setInterchainClient(icClient);
executionService.setExecutorEOA(executorEOA);
executionService.setGasOracle(address(gasOracle));
}
}
1 change: 0 additions & 1 deletion sin-executor/Makefile

This file was deleted.

7 changes: 7 additions & 0 deletions sin-executor/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include ../make/go.Makefile

generate: ## Generate code
cd $(GIT_ROOT)/packages/contracts-communication && yarn build:go
go generate ./...


9 changes: 5 additions & 4 deletions sin-executor/cmd/commands.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
"github.com/synapsecns/sanguine/core/commandline"
"github.com/synapsecns/sanguine/core/metrics"
"github.com/synapsecns/sanguine/sin-executor/config"
Expand Down Expand Up @@ -29,25 +30,25 @@ var runCommand = &cli.Command{

input, err := os.ReadFile(filepath.Clean(c.String(configFlag.Name)))
if err != nil {
return err
return fmt.Errorf("failed to read config file: %w", err)
}

metricsProvider := metrics.Get()

var cfg config.Config
err = yaml.Unmarshal(input, &cfg)
if err != nil {
return err
return fmt.Errorf("failed to unmarshal config: %w", err)
}

exec, err := executor.NewExecutor(c.Context, metricsProvider, cfg)
if err != nil {
return err
return fmt.Errorf("failed to create executor: %w", err)
}

err = exec.Start(c.Context)
if err != nil {
return err
return fmt.Errorf("failed to start executor: %w", err)
}

return nil
Expand Down
11 changes: 9 additions & 2 deletions sin-executor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (

// Config is the config for the Synapse module.
type Config struct {
// Chains is a map of chain IDs to chain configs.
Chains map[int]string `yaml:"chains"`
// Chains is a map of chain IDs to execution service contract addresses.
Chains map[int]ChainConfig `yaml:"chains"`
// OmnirpcURL is the URL of the Omni RPC.
OmnirpcURL string `yaml:"omnirpc_url"`
// Database is the database config.
Expand All @@ -20,6 +20,13 @@ type Config struct {
SubmitterConfig submitterConfig.Config `yaml:"submitter_config"`
}

type ChainConfig struct {
// ExecutionService is the address of the execution service contract.
ExecutionService string `yaml:"execution_service"`
// Client is the address of the interchain client contract.
Client string `yaml:"client"`
}

// DatabaseConfig represents the configuration for the database.
type DatabaseConfig struct {
Type string `yaml:"type"`
Expand Down
24 changes: 24 additions & 0 deletions sin-executor/contracts/executionservice/eventtype_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading