-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' of github.com:smartcontractkit/chainlink into …
…develop
- Loading branch information
Showing
36 changed files
with
957 additions
and
359 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"chainlink": minor | ||
--- | ||
|
||
#internal changes to core required by change BCF3168 in common to add relayer set |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"chainlink": patch | ||
--- | ||
|
||
generate gethwrappers for updating node operators in capability registry #internal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"chainlink": minor | ||
--- | ||
|
||
Moved test functions under evm package to support evm extraction #internal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@chainlink/contracts": patch | ||
--- | ||
|
||
Add function to update node operator' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import {BaseTest} from "./BaseTest.t.sol"; | ||
import {CapabilityRegistry} from "../CapabilityRegistry.sol"; | ||
|
||
contract CapabilityRegistry_UpdateNodeOperatorTest is BaseTest { | ||
event NodeOperatorUpdated(uint256 nodeOperatorId, address indexed admin, string name); | ||
|
||
uint256 private constant TEST_NODE_OPERATOR_ID = 0; | ||
address private constant NEW_NODE_OPERATOR_ADMIN = address(3); | ||
string private constant NEW_NODE_OPERATOR_NAME = "new-node-operator"; | ||
|
||
function setUp() public override { | ||
BaseTest.setUp(); | ||
changePrank(ADMIN); | ||
s_capabilityRegistry.addNodeOperators(_getNodeOperators()); | ||
} | ||
|
||
function test_RevertWhen_CalledByNonAdminAndNonOwner() public { | ||
changePrank(STRANGER); | ||
vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); | ||
|
||
CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); | ||
nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); | ||
|
||
uint256[] memory nodeOperatorIds = new uint256[](1); | ||
nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; | ||
s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); | ||
} | ||
|
||
function test_RevertWhen_NodeOperatorAdminIsZeroAddress() public { | ||
changePrank(ADMIN); | ||
vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); | ||
CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); | ||
nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: address(0), name: NEW_NODE_OPERATOR_NAME}); | ||
|
||
uint256[] memory nodeOperatorIds = new uint256[](1); | ||
nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; | ||
s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); | ||
} | ||
|
||
function test_UpdatesNodeOperator() public { | ||
changePrank(ADMIN); | ||
|
||
CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); | ||
nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); | ||
|
||
uint256[] memory nodeOperatorIds = new uint256[](1); | ||
nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; | ||
|
||
vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); | ||
emit NodeOperatorUpdated(TEST_NODE_OPERATOR_ID, NEW_NODE_OPERATOR_ADMIN, NEW_NODE_OPERATOR_NAME); | ||
s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); | ||
|
||
CapabilityRegistry.NodeOperator memory nodeOperator = s_capabilityRegistry.getNodeOperator(0); | ||
assertEq(nodeOperator.admin, NEW_NODE_OPERATOR_ADMIN); | ||
assertEq(nodeOperator.name, NEW_NODE_OPERATOR_NAME); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
package testutils | ||
|
||
import ( | ||
"fmt" | ||
"math/big" | ||
"net/http" | ||
"net/http/httptest" | ||
"net/url" | ||
"sync" | ||
"testing" | ||
"time" | ||
|
||
"github.com/gorilla/websocket" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"github.com/tidwall/gjson" | ||
|
||
evmclmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" | ||
) | ||
|
||
func NewEthClientMock(t *testing.T) *evmclmocks.Client { | ||
return evmclmocks.NewClient(t) | ||
} | ||
|
||
func NewEthClientMockWithDefaultChain(t *testing.T) *evmclmocks.Client { | ||
c := NewEthClientMock(t) | ||
c.On("ConfiguredChainID").Return(FixtureChainID).Maybe() | ||
//c.On("IsL2").Return(false).Maybe() | ||
return c | ||
} | ||
|
||
// JSONRPCHandler is called with the method and request param(s). | ||
// respResult will be sent immediately. notifyResult is optional, and sent after a short delay. | ||
type JSONRPCHandler func(reqMethod string, reqParams gjson.Result) JSONRPCResponse | ||
|
||
type JSONRPCResponse struct { | ||
Result, Notify string // raw JSON (i.e. quoted strings etc.) | ||
|
||
Error struct { | ||
Code int | ||
Message string | ||
} | ||
} | ||
|
||
type testWSServer struct { | ||
t *testing.T | ||
s *httptest.Server | ||
mu sync.RWMutex | ||
wsconns []*websocket.Conn | ||
wg sync.WaitGroup | ||
} | ||
|
||
// NewWSServer starts a websocket server which invokes callback for each message received. | ||
// If chainID is set, then eth_chainId calls will be automatically handled. | ||
func NewWSServer(t *testing.T, chainID *big.Int, callback JSONRPCHandler) (ts *testWSServer) { | ||
ts = new(testWSServer) | ||
ts.t = t | ||
ts.wsconns = make([]*websocket.Conn, 0) | ||
handler := ts.newWSHandler(chainID, callback) | ||
ts.s = httptest.NewServer(handler) | ||
t.Cleanup(ts.Close) | ||
return | ||
} | ||
|
||
func (ts *testWSServer) Close() { | ||
if func() bool { | ||
ts.mu.Lock() | ||
defer ts.mu.Unlock() | ||
if ts.wsconns == nil { | ||
ts.t.Log("Test WS server already closed") | ||
return false | ||
} | ||
ts.s.CloseClientConnections() | ||
ts.s.Close() | ||
for _, ws := range ts.wsconns { | ||
ws.Close() | ||
} | ||
ts.wsconns = nil // nil indicates server closed | ||
return true | ||
}() { | ||
ts.wg.Wait() | ||
} | ||
} | ||
|
||
func (ts *testWSServer) WSURL() *url.URL { | ||
return WSServerURL(ts.t, ts.s) | ||
} | ||
|
||
// WSServerURL returns a ws:// url for the server | ||
func WSServerURL(t *testing.T, s *httptest.Server) *url.URL { | ||
u, err := url.Parse(s.URL) | ||
require.NoError(t, err, "Failed to parse url") | ||
u.Scheme = "ws" | ||
return u | ||
} | ||
|
||
func (ts *testWSServer) MustWriteBinaryMessageSync(t *testing.T, msg string) { | ||
ts.mu.Lock() | ||
defer ts.mu.Unlock() | ||
conns := ts.wsconns | ||
if len(conns) != 1 { | ||
t.Fatalf("expected 1 conn, got %d", len(conns)) | ||
} | ||
conn := conns[0] | ||
err := conn.WriteMessage(websocket.BinaryMessage, []byte(msg)) | ||
require.NoError(t, err) | ||
} | ||
|
||
func (ts *testWSServer) newWSHandler(chainID *big.Int, callback JSONRPCHandler) (handler http.HandlerFunc) { | ||
if callback == nil { | ||
callback = func(method string, params gjson.Result) (resp JSONRPCResponse) { return } | ||
} | ||
t := ts.t | ||
upgrader := websocket.Upgrader{ | ||
CheckOrigin: func(r *http.Request) bool { return true }, | ||
} | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
ts.mu.Lock() | ||
if ts.wsconns == nil { // closed | ||
ts.mu.Unlock() | ||
return | ||
} | ||
ts.wg.Add(1) | ||
defer ts.wg.Done() | ||
conn, err := upgrader.Upgrade(w, r, nil) | ||
if !assert.NoError(t, err, "Failed to upgrade WS connection") { | ||
ts.mu.Unlock() | ||
return | ||
} | ||
defer conn.Close() | ||
ts.wsconns = append(ts.wsconns, conn) | ||
ts.mu.Unlock() | ||
|
||
for { | ||
_, data, err := conn.ReadMessage() | ||
if err != nil { | ||
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseAbnormalClosure) { | ||
ts.t.Log("Websocket closing") | ||
return | ||
} | ||
ts.t.Logf("Failed to read message: %v", err) | ||
return | ||
} | ||
ts.t.Log("Received message", string(data)) | ||
req := gjson.ParseBytes(data) | ||
if !req.IsObject() { | ||
ts.t.Logf("Request must be object: %v", req.Type) | ||
return | ||
} | ||
if e := req.Get("error"); e.Exists() { | ||
ts.t.Logf("Received jsonrpc error: %v", e) | ||
continue | ||
} | ||
m := req.Get("method") | ||
if m.Type != gjson.String { | ||
ts.t.Logf("Method must be string: %v", m.Type) | ||
return | ||
} | ||
|
||
var resp JSONRPCResponse | ||
if chainID != nil && m.String() == "eth_chainId" { | ||
resp.Result = `"0x` + chainID.Text(16) + `"` | ||
} else if m.String() == "eth_syncing" { | ||
resp.Result = "false" | ||
} else { | ||
resp = callback(m.String(), req.Get("params")) | ||
} | ||
id := req.Get("id") | ||
var msg string | ||
if resp.Error.Message != "" { | ||
msg = fmt.Sprintf(`{"jsonrpc":"2.0","id":%s,"error":{"code":%d,"message":"%s"}}`, id, resp.Error.Code, resp.Error.Message) | ||
} else { | ||
msg = fmt.Sprintf(`{"jsonrpc":"2.0","id":%s,"result":%s}`, id, resp.Result) | ||
} | ||
ts.t.Logf("Sending message: %v", msg) | ||
ts.mu.Lock() | ||
err = conn.WriteMessage(websocket.BinaryMessage, []byte(msg)) | ||
ts.mu.Unlock() | ||
if err != nil { | ||
ts.t.Logf("Failed to write message: %v", err) | ||
return | ||
} | ||
|
||
if resp.Notify != "" { | ||
time.Sleep(100 * time.Millisecond) | ||
msg := fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x00","result":%s}}`, resp.Notify) | ||
ts.t.Log("Sending message", msg) | ||
ts.mu.Lock() | ||
err = conn.WriteMessage(websocket.BinaryMessage, []byte(msg)) | ||
ts.mu.Unlock() | ||
if err != nil { | ||
ts.t.Logf("Failed to write message: %v", err) | ||
return | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package testutils | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/smartcontractkit/chainlink-common/pkg/logger" | ||
|
||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" | ||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" | ||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" | ||
) | ||
|
||
func NewTestChainScopedConfig(t testing.TB, overrideFn func(c *toml.EVMConfig)) config.ChainScopedConfig { | ||
var chainID = (*big.Big)(FixtureChainID) | ||
evmCfg := &toml.EVMConfig{ | ||
ChainID: chainID, | ||
Chain: toml.Defaults(chainID), | ||
} | ||
|
||
if overrideFn != nil { | ||
// We need to get the chainID from the override function first to load the correct chain defaults. | ||
// Then we apply the override values on top | ||
overrideFn(evmCfg) | ||
evmCfg.Chain = toml.Defaults(evmCfg.ChainID) | ||
overrideFn(evmCfg) | ||
} | ||
|
||
return config.NewTOMLChainScopedConfig(evmCfg, logger.Test(t)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package testutils | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" | ||
) | ||
|
||
func TestNewTestChainScopedConfigOverride(t *testing.T) { | ||
c := NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { | ||
finalityDepth := uint32(100) | ||
c.FinalityDepth = &finalityDepth | ||
}) | ||
|
||
// Overrides values | ||
assert.Equal(t, uint32(100), c.EVM().FinalityDepth()) | ||
// fallback.toml values | ||
assert.Equal(t, false, c.EVM().GasEstimator().EIP1559DynamicFees()) | ||
|
||
} |
Oops, something went wrong.