diff --git a/conf/config.go b/conf/config.go index b260cb19..c6eae482 100644 --- a/conf/config.go +++ b/conf/config.go @@ -134,6 +134,9 @@ type GatewayConfig struct { // OasisRPCs controls whether to enable the `oasis_*` methods. Default is not exposed. ExposeOasisRPCs bool `koanf:"oasis_rpcs"` + + // AllowUnencryptedTxs also accepts transacions with CallFormat=0. Default is false. + AllowUnencryptedTxs bool `koanf:"allow_unencrypted_txs"` } // GatewayMonitoringConfig is the gateway prometheus configuration. diff --git a/conf/server.yml b/conf/server.yml index 23ac83a8..854ab66d 100644 --- a/conf/server.yml +++ b/conf/server.yml @@ -36,4 +36,5 @@ gateway: port: 9999 method_limits: get_logs_max_rounds: 100 - oasis_rpcs: false + oasis_rpcs: true + allow_unencrypted_txs: false diff --git a/conf/tests-c10l.yml b/conf/tests-c10l.yml new file mode 100644 index 00000000..9bcca53d --- /dev/null +++ b/conf/tests-c10l.yml @@ -0,0 +1,38 @@ +runtime_id: "8000000000000000000000000000000000000000000000000000000000000000" +node_address: "unix:/tmp/eth-runtime-test/net-runner/network/client-0/internal.sock" + +log: + level: debug + format: json + +cache: + block_size: 10 + metrics: true + +database: + host: "127.0.0.1" + port: 5432 + db: "postgres" + user: "postgres" + password: "postgres" + dial_timeout: 5 + read_timeout: 10 + write_timeout: 5 + max_open_conns: 0 + +gateway: + chain_id: 42262 + http: + host: "localhost" + port: 8545 + ws: + host: "localhost" + port: 8546 + monitoring: + host: "localhost" + port: 9999 + method_limits: + get_logs_max_rounds: 100 + oasis_rpcs: true + allow_unencrypted_txs: false + diff --git a/rpc/apis.go b/rpc/apis.go index 98c602f2..c649528f 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -34,7 +34,7 @@ func GetRPCAPIs( var apis []ethRpc.API web3Service := web3.NewPublicAPI() - ethService := eth.NewPublicAPI(client, archiveClient, logging.GetLogger("eth_rpc"), config.ChainID, backend, gasPriceOracle, config.MethodLimits) + ethService := eth.NewPublicAPI(client, archiveClient, logging.GetLogger("eth_rpc"), config.ChainID, backend, gasPriceOracle, config.MethodLimits, !config.ExposeOasisRPCs || config.AllowUnencryptedTxs) netService := net.NewPublicAPI(config.ChainID) txpoolService := txpool.NewPublicAPI() filtersService := filters.NewPublicAPI(client, logging.GetLogger("eth_filters"), backend, eventSystem) diff --git a/rpc/eth/api.go b/rpc/eth/api.go index 143aa3d5..9e3f67ef 100644 --- a/rpc/eth/api.go +++ b/rpc/eth/api.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rlp" ethrpc "github.com/ethereum/go-ethereum/rpc" + "github.com/oasisprotocol/oasis-core/go/common/cbor" "github.com/oasisprotocol/oasis-core/go/common/logging" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/client" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/crypto/signature/secp256k1" @@ -108,13 +109,14 @@ type API interface { } type publicAPI struct { - client client.RuntimeClient - archiveClient *archive.Client - backend indexer.Backend - gasPriceOracle gas.Backend - chainID uint32 - Logger *logging.Logger - methodLimits *conf.MethodLimits + client client.RuntimeClient + archiveClient *archive.Client + backend indexer.Backend + gasPriceOracle gas.Backend + chainID uint32 + Logger *logging.Logger + methodLimits *conf.MethodLimits + allowUnencryptedTxs bool } // NewPublicAPI creates an instance of the public ETH Web3 API. @@ -126,15 +128,17 @@ func NewPublicAPI( backend indexer.Backend, gasPriceOracle gas.Backend, methodLimits *conf.MethodLimits, + allowUnencryptedTxes bool, ) API { return &publicAPI{ - client: client, - archiveClient: archiveClient, - chainID: chainID, - Logger: logger, - backend: backend, - gasPriceOracle: gasPriceOracle, - methodLimits: methodLimits, + client: client, + archiveClient: archiveClient, + chainID: chainID, + Logger: logger, + backend: backend, + gasPriceOracle: gasPriceOracle, + methodLimits: methodLimits, + allowUnencryptedTxs: allowUnencryptedTxes, } } @@ -463,6 +467,13 @@ func (api *publicAPI) SendRawTransaction(ctx context.Context, data hexutil.Bytes return common.Hash{}, ErrMalformedTransaction } + if !api.checkOasisTxEncrypted(ethTx.Data()) { + logger.Debug("dropped unencrypted transaction", "hash", ethTx.Hash()) + return common.Hash{}, ErrInvalidRequest + } + + ethTx.Data() + // Generate an Ethereum transaction that is handled by the EVM module. utx := types.UnverifiedTransaction{ Body: data, @@ -751,3 +762,28 @@ func (api *publicAPI) getBlockRound(ctx context.Context, logger *logging.Logger, return 0, nil } } + +// checkOasisTxEncrypted checks, if the Oasis transaction wrapped inside Ethereum tx is encrypted. +func (api *publicAPI) checkOasisTxEncrypted(data []byte) bool { + if api.allowUnencryptedTxs { + // Unencrypted transactions are allowed or encryption not supported by the gateway. + return true + } + if data == nil { + // Transaction is not Oasis transaction, ignore. + return true + } + + var tx types.Transaction + if err := cbor.Unmarshal(data, &tx); err != nil { + // Transaction is not Oasis transaction, ignore. + return true + } + + if tx.Call.Format == types.CallFormatPlain { + return false + } + + // Transaction marked as encrypted. + return true +}