Commit b8d9fa17 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #3479 from ethereum-optimism/develop

Develop -> Master
parents 3fe480d4 157ccc84
---
'@eth-optimism/contracts-bedrock': patch
---
Make spacer variables private in the Bridge and Messenger contracts so that they cannot be accessed in child contracts.
---
'@eth-optimism/indexer': minor
---
This release supports bedrock contracts and is configured for the public alpha testnet on goerli.
---
'@eth-optimism/proxyd': minor
---
Support per-method rate limiting
......@@ -5,7 +5,8 @@ go 1.17
replace github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
require (
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum-optimism/optimism/op-bindings v0.0.0
github.com/ethereum/go-ethereum v1.10.23
github.com/getsentry/sentry-go v0.12.0
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
......@@ -17,7 +18,6 @@ require (
)
require (
github.com/VictoriaMetrics/fastcache v1.9.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
......@@ -30,18 +30,15 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/go-bexpr v0.1.11 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.30.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/tsdb v0.10.0 // indirect
github.com/rjeczalik/notify v0.9.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
......
This diff is collapsed.
......@@ -35,6 +35,11 @@ var defaultBridgeCfgs = map[uint64][]*implConfig{
{"Standard", "StandardBridge", predeploys.DevL1StandardBridge},
{"ETH", "ETHBridge", predeploys.DevL1StandardBridge},
},
// Goerli
5: {
{"Standard", "StandardBridge", "0xFf94B6C486350aD92561Ba09bad3a59df764Da92"},
{"ETH", "ETHBridge", "0xFf94B6C486350aD92561Ba09bad3a59df764Da92"},
},
}
var customBridgeCfgs = map[uint64][]*implConfig{
......
......@@ -33,6 +33,10 @@ var defaultBridgeCfgs = map[uint64][]*implConfig{
901: {
{"Standard", "StandardBridge", L2StandardBridgeAddr},
},
// Goerli Alpha Testnet
28528: {
{"Standard", "StandardBridge", L2StandardBridgeAddr},
},
}
var customBridgeCfgs = map[uint64][]*implConfig{
......
This diff is collapsed.
......@@ -13,7 +13,7 @@ const WETH9StorageLayoutJSON = "{\"storage\":[{\"astId\":4,\"contract\":\"contra
var WETH9StorageLayout = new(solc.StorageLayout)
var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a72315820b2282f823392ab6b42c17b31235784e88e108cd8d10e77cd732aa3e1e7a88a7d64736f6c63430005110032"
var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a7231582092e8fa1999c122c50a7672ead4cd9cdd378070b1e8a202f4537418ba1398d60c64736f6c63430005110032"
func init() {
if err := json.Unmarshal([]byte(WETH9StorageLayoutJSON), WETH9StorageLayout); err != nil {
......
package crossdomain
import (
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)
var (
// NonceMask represents a mask used to extract version bytes from the nonce
NonceMask, _ = new(big.Int).SetString("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
// relayMessage0ABI represents the v0 relay message encoding
relayMessage0ABI = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_messageNonce\",\"type\":\"uint256\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
// relayMessage1ABI represents the v1 relay message encoding
relayMessage1ABI = "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]"
// relayMessage0 represents the ABI of relay message v0
relayMessage0 abi.ABI
// relayMessage1 represents the ABI of relay message v1
relayMessage1 abi.ABI
)
// Create the required ABIs
func init() {
var err error
relayMessage0, err = abi.JSON(strings.NewReader(relayMessage0ABI))
if err != nil {
panic(err)
}
relayMessage1, err = abi.JSON(strings.NewReader(relayMessage1ABI))
if err != nil {
panic(err)
}
}
// EncodeCrossDomainMessageV0 will encode the calldata for
// "relayMessage(address,address,bytes,uint256)",
func EncodeCrossDomainMessageV0(
target *common.Address,
sender *common.Address,
message []byte,
nonce *big.Int,
) ([]byte, error) {
return relayMessage0.Pack("relayMessage", target, sender, message, nonce)
}
// EncodeCrossDomainMessageV1 will encode the calldata for
// "relayMessage(uint256,address,address,uint256,uint256,bytes)",
func EncodeCrossDomainMessageV1(
nonce *big.Int,
sender *common.Address,
target *common.Address,
value *big.Int,
gasLimit *big.Int,
data []byte,
) ([]byte, error) {
return relayMessage1.Pack("relayMessage", nonce, sender, target, value, gasLimit, data)
}
// DecodeVersionedNonce will decode the version that is encoded in the nonce
func DecodeVersionedNonce(versioned *big.Int) (*big.Int, *big.Int) {
nonce := new(big.Int).And(versioned, NonceMask)
version := new(big.Int).Rsh(versioned, 240)
return nonce, version
}
// EncodeVersionedNonce will encode the version into the nonce
func EncodeVersionedNonce(nonce, version *big.Int) *big.Int {
shifted := new(big.Int).Lsh(version, 240)
return new(big.Int).Or(nonce, shifted)
}
package crossdomain_test
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/stretchr/testify/require"
)
func FuzzVersionedNonce(f *testing.F) {
f.Fuzz(func(t *testing.T, _nonce []byte, _version uint16) {
inputNonce := new(big.Int).SetBytes(_nonce)
// Clamp nonce to uint240
if inputNonce.Cmp(crossdomain.NonceMask) > 0 {
inputNonce = new(big.Int).Set(crossdomain.NonceMask)
}
// Clamp version to 0 or 1
_version = _version % 2
inputVersion := new(big.Int).SetUint64(uint64(_version))
encodedNonce := crossdomain.EncodeVersionedNonce(inputNonce, inputVersion)
decodedNonce, decodedVersion := crossdomain.DecodeVersionedNonce(encodedNonce)
require.Equal(t, decodedNonce.Uint64(), inputNonce.Uint64())
require.Equal(t, decodedVersion.Uint64(), inputVersion.Uint64())
})
}
package crossdomain
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
// HashCrossDomainMessageV0 computes the pre bedrock cross domain messaging
// hashing scheme.
func HashCrossDomainMessageV0(
target *common.Address,
sender *common.Address,
data []byte,
nonce *big.Int,
) (common.Hash, error) {
encoded, err := EncodeCrossDomainMessageV0(target, sender, data, nonce)
if err != nil {
return common.Hash{}, err
}
hash := crypto.Keccak256(encoded)
return common.BytesToHash(hash), nil
}
// HashCrossDomainMessageV1 computes the first post bedrock cross domain
// messaging hashing scheme.
func HashCrossDomainMessageV1(
nonce *big.Int,
sender *common.Address,
target *common.Address,
value *big.Int,
gasLimit *big.Int,
data []byte,
) (common.Hash, error) {
encoded, err := EncodeCrossDomainMessageV1(nonce, sender, target, value, gasLimit, data)
if err != nil {
return common.Hash{}, err
}
hash := crypto.Keccak256(encoded)
return common.BytesToHash(hash), nil
}
package crossdomain
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
// CrossDomainMessage represents a cross domain message
// used by the CrossDomainMessenger. The version is encoded
// in the nonce. Version 0 messages do not have a value,
// version 1 messages have a value and the most significant
// byte of the nonce is a 1
type CrossDomainMessage struct {
Nonce *big.Int
Sender *common.Address
Target *common.Address
Value *big.Int
GasLimit *big.Int
Data []byte
}
// NewCrossDomainMessage creates a CrossDomainMessage.
func NewCrossDomainMessage(
nonce *big.Int,
sender, target *common.Address,
value, gasLimit *big.Int,
data []byte,
) *CrossDomainMessage {
return &CrossDomainMessage{
Nonce: nonce,
Sender: sender,
Target: target,
Value: value,
GasLimit: gasLimit,
Data: data,
}
}
// Version will return the version of the CrossDomainMessage.
// It does this by looking at the first byte of the nonce.
func (c *CrossDomainMessage) Version() uint64 {
_, version := DecodeVersionedNonce(c.Nonce)
return version.Uint64()
}
// Encode will encode a cross domain message based on the version.
func (c *CrossDomainMessage) Encode() ([]byte, error) {
version := c.Version()
switch version {
case 0:
return EncodeCrossDomainMessageV0(c.Target, c.Sender, c.Data, c.Nonce)
case 1:
return EncodeCrossDomainMessageV1(c.Nonce, c.Sender, c.Target, c.Value, c.GasLimit, c.Data)
default:
return nil, fmt.Errorf("unknown nonce version %d", version)
}
}
// Hash will compute the hash of the CrossDomainMessage
func (c *CrossDomainMessage) Hash() (common.Hash, error) {
version := c.Version()
switch version {
case 0:
return HashCrossDomainMessageV0(c.Target, c.Sender, c.Data, c.Nonce)
case 1:
return HashCrossDomainMessageV1(c.Nonce, c.Sender, c.Target, c.Value, c.GasLimit, c.Data)
default:
return common.Hash{}, fmt.Errorf("unknown nonce version %d", version)
}
}
package crossdomain_test
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
)
// TestEncode tests the encoding of a CrossDomainMessage. The assertion was
// created using solidity.
func TestEncode(t *testing.T) {
t.Parallel()
t.Run("V0", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big0, common.Big0),
&common.Address{},
&common.Address{19: 0x01},
big.NewInt(0),
big.NewInt(5),
[]byte{},
)
require.Equal(t, uint64(0), msg.Version())
encoded, err := msg.Encode()
require.Nil(t, err)
expect := hexutil.MustDecode("0xcbd4ece900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(t, expect, encoded)
})
t.Run("V1", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big1, common.Big1),
&common.Address{19: 0x01},
&common.Address{19: 0x02},
big.NewInt(100),
big.NewInt(555),
[]byte{},
)
require.Equal(t, uint64(1), msg.Version())
encoded, err := msg.Encode()
require.Nil(t, err)
expect := hexutil.MustDecode("0xd764ad0b0001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000022b00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000")
require.Equal(t, expect, encoded)
})
}
// TestEncode tests the hash of a CrossDomainMessage. The assertion was
// created using solidity.
func TestHash(t *testing.T) {
t.Parallel()
t.Run("V0", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big0, common.Big0),
&common.Address{},
&common.Address{19: 0x01},
big.NewInt(10),
big.NewInt(5),
[]byte{},
)
require.Equal(t, uint64(0), msg.Version())
hash, err := msg.Hash()
require.Nil(t, err)
expect := common.HexToHash("0x5bb579a193681e7c4d43c8c2e4bc6c2c447d21ef9fa887ca23b2d3f9a0fac065")
require.Equal(t, expect, hash)
})
t.Run("V1", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big0, common.Big1),
&common.Address{},
&common.Address{19: 0x01},
big.NewInt(0),
big.NewInt(5),
[]byte{},
)
require.Equal(t, uint64(1), msg.Version())
hash, err := msg.Hash()
require.Nil(t, err)
expect := common.HexToHash("0x09bbda7f59cdaccab5c41cab4600bd458b2bd7d9f8410f13316fe07e5f4237cc")
require.Equal(t, expect, hash)
})
}
......@@ -17,6 +17,10 @@ CrossDomainOwnable2_Test:test_revertNotSetOnlyOwner2() (gas: 14598)
CrossDomainOwnable2_Test:test_revertOnlyOwner() (gas: 63704)
DeployerWhitelist_Test:test_owner() (gas: 7591)
DeployerWhitelist_Test:test_storageSlots() (gas: 33427)
Encoding_Test:test_decodeVersionedNonce_differential(uint240,uint16) (runs: 256, μ: 13329, ~: 13345)
Encoding_Test:test_encodeCrossDomainMessage_differential(uint240,uint8,address,address,uint256,uint256,bytes) (runs: 256, μ: 87650, ~: 91649)
Encoding_Test:test_encodeDepositTransaction_differential(address,address,uint256,uint256,uint64,bool,bytes,uint256) (runs: 256, μ: 106526, ~: 101730)
Encoding_Test:test_nonceVersioning(uint240,uint16) (runs: 256, μ: 652, ~: 652)
GasPriceOracle_Test:test_baseFee() (gas: 8392)
GasPriceOracle_Test:test_gasPrice() (gas: 8381)
GasPriceOracle_Test:test_l1BaseFee() (gas: 10648)
......@@ -30,13 +34,18 @@ GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 11739)
GasPriceOracle_Test:test_setOverhead() (gas: 36813)
GasPriceOracle_Test:test_setScalar() (gas: 36820)
GasPriceOracle_Test:test_storageLayout() (gas: 86777)
Hashing_Test:test_hashCrossDomainMessage_differential(uint256,address,address,uint256,uint256,bytes) (runs: 256, μ: 23905, ~: 23788)
Hashing_Test:test_hashDepositSource() (gas: 628)
Hashing_Test:test_hashDepositTransaction_differential(address,address,uint256,uint256,uint64,bytes,uint256) (runs: 256, μ: 66710, ~: 66432)
Hashing_Test:test_hashOutputRootProof_differential(bytes32,bytes32,bytes32,bytes32) (runs: 256, μ: 72062, ~: 93483)
Hashing_Test:test_hashWithdrawal_differential(uint256,address,address,uint256,uint256,bytes) (runs: 256, μ: 23654, ~: 23478)
L1BlockTest:test_basefee() (gas: 7575)
L1BlockTest:test_hash() (gas: 7552)
L1BlockTest:test_number() (gas: 7629)
L1BlockTest:test_sequenceNumber() (gas: 7650)
L1BlockTest:test_timestamp() (gas: 7661)
L1BlockTest:test_updateValues() (gas: 28193)
L1BlockTest:test_updatesValues(uint64,uint64,uint256,bytes32,uint64) (runs: 256, μ: 35307, ~: 35717)
L1BlockNumberTest:test_fallback() (gas: 18677)
L1BlockNumberTest:test_getL1BlockNumber() (gas: 10668)
L1BlockNumberTest:test_receive() (gas: 25340)
......@@ -55,7 +64,7 @@ L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 301590)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1492584)
L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 41003)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24283)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 84053)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 84071)
L1StandardBridge_Test:test_depositERC20() (gas: 574877)
L1StandardBridge_Test:test_depositERC20To() (gas: 577084)
L1StandardBridge_Test:test_depositETH() (gas: 369700)
......@@ -81,7 +90,7 @@ L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41
L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122833)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 138556)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10576)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 52558)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 52577)
L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26829)
L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25123)
L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91445)
......@@ -92,10 +101,10 @@ L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 23564)
L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 26424)
L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 25983)
L2OutputOracleTest:test_changeProposer() (gas: 56139)
L2OutputOracleTest:test_computeL2Timestamp() (gas: 30288)
L2OutputOracleTest:test_computeL2Timestamp() (gas: 30307)
L2OutputOracleTest:test_constructor() (gas: 49046)
L2OutputOracleTest:test_deleteOutput() (gas: 77242)
L2OutputOracleTest:test_getL2Output() (gas: 88508)
L2OutputOracleTest:test_getL2Output() (gas: 88546)
L2OutputOracleTest:test_latestBlockNumber() (gas: 76284)
L2OutputOracleTest:test_nextBlockNumber() (gas: 15232)
L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 75046)
......@@ -144,10 +153,11 @@ OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10813)
OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15789)
OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15967)
OptimismPortalUpgradeable_Test:test_upgrading() (gas: 180632)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInsufficientGas() (gas: 160788)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_differential(address,address,uint256,uint256,bytes) (runs: 256, μ: 265023, ~: 265729)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInsufficientGas() (gas: 158288)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInvalidOutputRootProof() (gas: 81241)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnRecentWithdrawal() (gas: 53001)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReentrancy() (gas: 205354)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnRecentWithdrawal() (gas: 50501)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReentrancy() (gas: 202854)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReplay() (gas: 278729)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnSelfCall() (gas: 50539)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOninvalidWithdrawalProof() (gas: 148562)
......@@ -164,20 +174,20 @@ OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreat
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75881)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83333)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 83993)
OptimismPortal_Test:test_isBlockFinalized() (gas: 113725)
OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 26630)
OptimismPortal_Test:test_isBlockFinalized() (gas: 113744)
OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 24130)
Proxy_Test:test_clashingFunctionSignatures() (gas: 101427)
Proxy_Test:test_implementationKey() (gas: 20942)
Proxy_Test:test_implementationProxyCallIfNotAdmin() (gas: 30021)
Proxy_Test:test_implementationZeroAddress() (gas: 47604)
Proxy_Test:test_itDelegatesToTheImplementation() (gas: 45251)
Proxy_Test:test_ownerKey() (gas: 19091)
Proxy_Test:test_ownerProxyCallIfNotAdmin() (gas: 34711)
Proxy_Test:test_ownerProxyCallIfNotAdmin() (gas: 34729)
Proxy_Test:test_payableUpgradeToAndCall() (gas: 53865)
Proxy_Test:test_revertUpgradeToAndCall() (gas: 104654)
Proxy_Test:test_revertUpgradeToAndCall() (gas: 104727)
Proxy_Test:test_upgradeToAndCall() (gas: 125305)
Proxy_Test:test_zeroAddressCaller() (gas: 14825)
ProxyAdmin_Test:test_chugsplashChangeProxyAdmin() (gas: 35623)
ProxyAdmin_Test:test_chugsplashChangeProxyAdmin() (gas: 35642)
ProxyAdmin_Test:test_chugsplashGetProxyAdmin() (gas: 15683)
ProxyAdmin_Test:test_chugsplashGetProxyImplementation() (gas: 51149)
ProxyAdmin_Test:test_chugsplashUpgrade() (gas: 48960)
......@@ -187,7 +197,7 @@ ProxyAdmin_Test:test_delegateResolvedGetProxyAdmin() (gas: 17699)
ProxyAdmin_Test:test_delegateResolvedGetProxyImplementation() (gas: 62115)
ProxyAdmin_Test:test_delegateResolvedUpgrade() (gas: 58520)
ProxyAdmin_Test:test_delegateResolvedUpgradeAndCall() (gas: 97989)
ProxyAdmin_Test:test_erc1967ChangeProxyAdmin() (gas: 33851)
ProxyAdmin_Test:test_erc1967ChangeProxyAdmin() (gas: 33870)
ProxyAdmin_Test:test_erc1967GetProxyAdmin() (gas: 15669)
ProxyAdmin_Test:test_erc1967GetProxyImplementation() (gas: 52093)
ProxyAdmin_Test:test_erc1967Upgrade() (gas: 50030)
......@@ -282,6 +292,7 @@ ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20571)
ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20594)
ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017134)
ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16058)
SafeCall_Test:test_safeCall(address,address,uint256,uint64,bytes) (runs: 256, μ: 43632, ~: 45833)
Semver_Test:test_behindProxy() (gas: 506906)
Semver_Test:test_version() (gas: 9487)
SequencerFeeVault_Test:test_constructor() (gas: 7678)
......
......@@ -21,13 +21,13 @@ contract GasPriceOracle is Ownable, Semver {
* @custom:legacy
* @notice Spacer for backwards compatibility.
*/
uint256 internal spacer0;
uint256 private spacer0;
/**
* @custom:legacy
* @notice Spacer for backwards compatibility.
*/
uint256 internal spacer1;
uint256 private spacer1;
/**
* @notice Constant L1 gas overhead per transaction.
......
......@@ -27,7 +27,7 @@ contract CrossDomainMessengerLegacySpacer {
* @custom:spacer libAddressManager
* @notice Spacer for backwards compatibility.
*/
address internal spacer0;
address private spacer0;
}
/**
......@@ -91,14 +91,14 @@ abstract contract CrossDomainMessenger is
* @custom:spacer blockedMessages
* @notice Spacer for backwards compatibility.
*/
uint256 internal spacer1;
uint256 private spacer1;
/**
* @custom:legacy
* @custom:spacer relayedMessages
* @notice Spacer for backwards compatibility.
*/
uint256 internal spacer2;
uint256 private spacer2;
/**
* @notice Mapping of message hashes to boolean receipt values. Note that a message will only
......
......@@ -36,13 +36,13 @@ abstract contract StandardBridge {
* @custom:legacy
* @notice Spacer for backwards compatibility.
*/
uint256 internal spacer0;
uint256 private spacer0;
/**
* @custom:legacy
* @notice Spacer for backwards compatibility.
*/
uint256 internal spacer1;
uint256 private spacer1;
/**
* @notice Mapping that stores deposits for a given pair of local and remote tokens.
......
......@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"strings"
"time"
)
type ServerConfig struct {
......@@ -40,10 +41,28 @@ type MetricsConfig struct {
}
type RateLimitConfig struct {
RatePerSecond int `toml:"rate_per_second"`
ExemptOrigins []string `toml:"exempt_origins"`
ExemptUserAgents []string `toml:"exempt_user_agents"`
ErrorMessage string `toml:"error_message"`
RatePerSecond int `toml:"rate_per_second"`
ExemptOrigins []string `toml:"exempt_origins"`
ExemptUserAgents []string `toml:"exempt_user_agents"`
ErrorMessage string `toml:"error_message"`
MethodOverrides map[string]*RateLimitMethodOverride `toml:"method_overrides"`
}
type RateLimitMethodOverride struct {
Limit int `toml:"limit"`
Interval TOMLDuration `toml:"interval"`
}
type TOMLDuration time.Duration
func (t *TOMLDuration) UnmarshalText(b []byte) error {
d, err := time.ParseDuration(string(b))
if err != nil {
return err
}
*t = TOMLDuration(d)
return nil
}
type BackendOptions struct {
......
package integration_tests
import (
"encoding/json"
"net/http"
"os"
"testing"
......@@ -17,6 +18,8 @@ type resWithCode struct {
const frontendOverLimitResponse = `{"error":{"code":-32016,"message":"over rate limit"},"id":null,"jsonrpc":"2.0"}`
var ethChainID = "eth_chainId"
func TestBackendMaxRPSLimit(t *testing.T) {
goodBackend := NewMockBackend(BatchedResponseHandler(200, goodResponse))
defer goodBackend.Close()
......@@ -28,8 +31,7 @@ func TestBackendMaxRPSLimit(t *testing.T) {
shutdown, err := proxyd.Start(config)
require.NoError(t, err)
defer shutdown()
limitedRes, codes := spamReqs(t, client, 503)
limitedRes, codes := spamReqs(t, client, ethChainID, 503)
require.Equal(t, 2, codes[200])
require.Equal(t, 1, codes[503])
RequireEqualJSON(t, []byte(noBackendsResponse), limitedRes)
......@@ -48,7 +50,7 @@ func TestFrontendMaxRPSLimit(t *testing.T) {
t.Run("non-exempt over limit", func(t *testing.T) {
client := NewProxydClient("http://127.0.0.1:8545")
limitedRes, codes := spamReqs(t, client, 429)
limitedRes, codes := spamReqs(t, client, ethChainID, 429)
require.Equal(t, 1, codes[429])
require.Equal(t, 2, codes[200])
RequireEqualJSON(t, []byte(frontendOverLimitResponse), limitedRes)
......@@ -58,7 +60,7 @@ func TestFrontendMaxRPSLimit(t *testing.T) {
h := make(http.Header)
h.Set("User-Agent", "exempt_agent")
client := NewProxydClientWithHeaders("http://127.0.0.1:8545", h)
_, codes := spamReqs(t, client, 429)
_, codes := spamReqs(t, client, ethChainID, 429)
require.Equal(t, 3, codes[200])
})
......@@ -66,7 +68,7 @@ func TestFrontendMaxRPSLimit(t *testing.T) {
h := make(http.Header)
h.Set("Origin", "exempt_origin")
client := NewProxydClientWithHeaders("http://127.0.0.1:8545", h)
_, codes := spamReqs(t, client, 429)
_, codes := spamReqs(t, client, ethChainID, 429)
require.Equal(t, 3, codes[200])
})
......@@ -77,24 +79,72 @@ func TestFrontendMaxRPSLimit(t *testing.T) {
h2.Set("X-Forwarded-For", "1.1.1.1")
client1 := NewProxydClientWithHeaders("http://127.0.0.1:8545", h1)
client2 := NewProxydClientWithHeaders("http://127.0.0.1:8545", h2)
_, codes := spamReqs(t, client1, 429)
_, codes := spamReqs(t, client1, ethChainID, 429)
require.Equal(t, 1, codes[429])
require.Equal(t, 2, codes[200])
_, code, err := client2.SendRPC("eth_chainId", nil)
_, code, err := client2.SendRPC(ethChainID, nil)
require.Equal(t, 200, code)
require.NoError(t, err)
time.Sleep(time.Second)
_, code, err = client2.SendRPC("eth_chainId", nil)
_, code, err = client2.SendRPC(ethChainID, nil)
require.Equal(t, 200, code)
require.NoError(t, err)
})
time.Sleep(time.Second)
t.Run("RPC override", func(t *testing.T) {
client := NewProxydClient("http://127.0.0.1:8545")
limitedRes, codes := spamReqs(t, client, "eth_foobar", 429)
// use 2 and 1 here since the limit for eth_foobar is 1
require.Equal(t, 2, codes[429])
require.Equal(t, 1, codes[200])
RequireEqualJSON(t, []byte(frontendOverLimitResponse), limitedRes)
})
time.Sleep(time.Second)
t.Run("RPC override in batch", func(t *testing.T) {
client := NewProxydClient("http://127.0.0.1:8545")
req := NewRPCReq("123", "eth_foobar", nil)
out, code, err := client.SendBatchRPC(req, req, req)
require.NoError(t, err)
var res []proxyd.RPCRes
require.NoError(t, json.Unmarshal(out, &res))
expCode := proxyd.ErrOverRateLimit.Code
require.Equal(t, 200, code)
require.Equal(t, 3, len(res))
require.Nil(t, res[0].Error)
require.Equal(t, expCode, res[1].Error.Code)
require.Equal(t, expCode, res[2].Error.Code)
})
time.Sleep(time.Second)
t.Run("RPC override in batch exempt", func(t *testing.T) {
h := make(http.Header)
h.Set("User-Agent", "exempt_agent")
client := NewProxydClientWithHeaders("http://127.0.0.1:8545", h)
req := NewRPCReq("123", "eth_foobar", nil)
out, code, err := client.SendBatchRPC(req, req, req)
require.NoError(t, err)
var res []proxyd.RPCRes
require.NoError(t, json.Unmarshal(out, &res))
require.Equal(t, 200, code)
require.Equal(t, 3, len(res))
require.Nil(t, res[0].Error)
require.Nil(t, res[1].Error)
require.Nil(t, res[2].Error)
})
}
func spamReqs(t *testing.T, client *ProxydHTTPClient, limCode int) ([]byte, map[int]int) {
func spamReqs(t *testing.T, client *ProxydHTTPClient, method string, limCode int) ([]byte, map[int]int) {
resCh := make(chan *resWithCode)
for i := 0; i < 3; i++ {
go func() {
res, code, err := client.SendRPC("eth_chainId", nil)
res, code, err := client.SendRPC(method, nil)
require.NoError(t, err)
resCh <- &resWithCode{
code: code,
......
......@@ -15,9 +15,14 @@ backends = ["good"]
[rpc_method_mappings]
eth_chainId = "main"
eth_foobar = "main"
[rate_limit]
rate_per_second = 2
exempt_origins = ["exempt_origin"]
exempt_user_agents = ["exempt_agent"]
error_message = "over rate limit"
[rate_limit.method_overrides.eth_foobar]
limit = 1
interval = "1s"
\ No newline at end of file
......@@ -49,7 +49,8 @@ type Server struct {
timeout time.Duration
maxUpstreamBatchSize int
upgrader *websocket.Upgrader
lim limiter.Store
mainLim limiter.Store
overrideLims map[string]limiter.Store
limConfig RateLimitConfig
limExemptOrigins map[string]bool
limExemptUserAgents map[string]bool
......@@ -59,6 +60,8 @@ type Server struct {
srvMu sync.Mutex
}
type limiterFunc func(method string) bool
func NewServer(
backendGroups map[string]*BackendGroup,
wsBackendGroup *BackendGroup,
......@@ -89,12 +92,12 @@ func NewServer(
maxUpstreamBatchSize = defaultMaxUpstreamBatchSize
}
var lim limiter.Store
var mainLim limiter.Store
limExemptOrigins := make(map[string]bool)
limExemptUserAgents := make(map[string]bool)
if rateLimitConfig.RatePerSecond > 0 {
var err error
lim, err = memorystore.New(&memorystore.Config{
mainLim, err = memorystore.New(&memorystore.Config{
Tokens: uint64(rateLimitConfig.RatePerSecond),
Interval: time.Second,
})
......@@ -109,7 +112,19 @@ func NewServer(
limExemptUserAgents[strings.ToLower(agent)] = true
}
} else {
lim, _ = noopstore.New()
mainLim, _ = noopstore.New()
}
overrideLims := make(map[string]limiter.Store)
for method, override := range rateLimitConfig.MethodOverrides {
var err error
overrideLims[method], err = memorystore.New(&memorystore.Config{
Tokens: uint64(override.Limit),
Interval: time.Duration(override.Interval),
})
if err != nil {
return nil, err
}
}
return &Server{
......@@ -127,7 +142,8 @@ func NewServer(
upgrader: &websocket.Upgrader{
HandshakeTimeout: 5 * time.Second,
},
lim: lim,
mainLim: mainLim,
overrideLims: overrideLims,
limConfig: rateLimitConfig,
limExemptOrigins: limExemptOrigins,
limExemptUserAgents: limExemptUserAgents,
......@@ -197,22 +213,37 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
userAgent := r.Header.Get("User-Agent")
exemptOrigin := s.limExemptOrigins[strings.ToLower(origin)]
exemptUserAgent := s.limExemptUserAgents[strings.ToLower(userAgent)]
// Use XFF in context since it will automatically be replaced by the remote IP
xff := stripXFF(GetXForwardedFor(ctx))
var ok bool
if exemptOrigin || exemptUserAgent {
ok = true
} else {
if xff == "" {
log.Warn("rejecting request without XFF or remote IP")
ok = false
isUnlimitedOrigin := s.isUnlimitedOrigin(origin)
isUnlimitedUserAgent := s.isUnlimitedUserAgent(userAgent)
if xff == "" {
writeRPCError(ctx, w, nil, ErrInvalidRequest("request does not include a remote IP"))
return
}
isLimited := func(method string) bool {
if isUnlimitedOrigin || isUnlimitedUserAgent {
return false
}
var lim limiter.Store
if method == "" {
lim = s.mainLim
} else {
_, _, _, ok, _ = s.lim.Take(ctx, xff)
lim = s.overrideLims[method]
}
if lim == nil {
return false
}
_, _, _, ok, _ := lim.Take(ctx, xff)
return !ok
}
if !ok {
if isLimited("") {
rpcErr := ErrOverRateLimit.Clone()
rpcErr.Message = s.limConfig.ErrorMessage
RecordRPCError(ctx, BackendProxyd, "unknown", rpcErr)
......@@ -271,7 +302,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
return
}
batchRes, batchContainsCached, err := s.handleBatchRPC(ctx, reqs, true)
batchRes, batchContainsCached, err := s.handleBatchRPC(ctx, reqs, isLimited, true)
if err == context.DeadlineExceeded {
writeRPCError(ctx, w, nil, ErrGatewayTimeout)
return
......@@ -287,7 +318,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
}
rawBody := json.RawMessage(body)
backendRes, cached, err := s.handleBatchRPC(ctx, []json.RawMessage{rawBody}, false)
backendRes, cached, err := s.handleBatchRPC(ctx, []json.RawMessage{rawBody}, isLimited, false)
if err != nil {
writeRPCError(ctx, w, nil, ErrInternal)
return
......@@ -296,7 +327,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
writeRPCRes(ctx, w, backendRes[0])
}
func (s *Server) handleBatchRPC(ctx context.Context, reqs []json.RawMessage, isBatch bool) ([]*RPCRes, bool, error) {
func (s *Server) handleBatchRPC(ctx context.Context, reqs []json.RawMessage, isLimited limiterFunc, isBatch bool) ([]*RPCRes, bool, error) {
// A request set is transformed into groups of batches.
// Each batch group maps to a forwarded JSON-RPC batch request (subject to maxUpstreamBatchSize constraints)
// A groupID is used to decouple Requests that have duplicate ID so they're not part of the same batch that's
......@@ -347,6 +378,22 @@ func (s *Server) handleBatchRPC(ctx context.Context, reqs []json.RawMessage, isB
continue
}
// Take rate limit for specific methods.
// NOTE: eventually, this should apply to all batch requests. However,
// since we don't have data right now on the size of each batch, we
// only apply this to the methods that have an additional rate limit.
if _, ok := s.overrideLims[parsedReq.Method]; ok && isLimited(parsedReq.Method) {
log.Info(
"rate limited specific RPC",
"source", "rpc",
"req_id", GetReqID(ctx),
"method", parsedReq.Method,
)
RecordRPCError(ctx, BackendProxyd, parsedReq.Method, ErrOverRateLimit)
responses[i] = NewRPCErrorRes(parsedReq.ID, ErrOverRateLimit)
continue
}
id := string(parsedReq.ID)
// If this is a duplicate Request ID, move the Request to a new batchGroup
ids[id]++
......@@ -494,6 +541,14 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context
)
}
func (s *Server) isUnlimitedOrigin(origin string) bool {
return s.limExemptOrigins[strings.ToLower(origin)]
}
func (s *Server) isUnlimitedUserAgent(origin string) bool {
return s.limExemptUserAgents[strings.ToLower(origin)]
}
func setCacheHeader(w http.ResponseWriter, cached bool) {
if cached {
w.Header().Set(cacheStatusHdr, "HIT")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment