From 63c0338db4408aba686a42db8f606137f89717e4 Mon Sep 17 00:00:00 2001
From: Jonathan Combs <150135962+JonathanTylerCombs@users.noreply.github.com>
Date: Thu, 23 May 2024 02:29:06 -0400
Subject: [PATCH] Add files via upload
---
.github/workflows/api.go | 337 +++++++
.github/workflows/api_test.go | 355 ++++++++
.github/workflows/auth0-integration.pdf | Bin 0 -> 83721 bytes
.github/workflows/config.go | 480 ++++++++++
.github/workflows/config_test.go | 153 ++++
.github/workflows/defaults.go | 134 +++
.github/workflows/doc.go | 121 +++
.github/workflows/endpoints.go | 91 ++
.github/workflows/errors.go | 52 ++
.github/workflows/full-node-ansible.md | 136 +++
.github/workflows/full-node-binaries.md | 181 ++++
.github/workflows/full-node-docker.md | 482 ++++++++++
.github/workflows/full-node-gcp.md | 102 +++
.github/workflows/full-node-packages.md | 161 ++++
.../full-node-system-requirements.md | 19 +
.github/workflows/jwt_auth.go | 45 +
.github/workflows/jwt_handler.go | 80 ++
.github/workflows/lifecycle.go | 31 +
.github/workflows/main.go | 209 +++++
.github/workflows/node.go | 824 ++++++++++++++++++
.github/workflows/node_auth_test.go | 237 +++++
.github/workflows/node_example_test.go | 59 ++
.github/workflows/node_test.go | 638 ++++++++++++++
.github/workflows/rpcstack.go | 651 ++++++++++++++
.github/workflows/rpcstack_test.go | 616 +++++++++++++
.github/workflows/utils_test.go | 106 +++
26 files changed, 6300 insertions(+)
create mode 100644 .github/workflows/api.go
create mode 100644 .github/workflows/api_test.go
create mode 100644 .github/workflows/auth0-integration.pdf
create mode 100644 .github/workflows/config.go
create mode 100644 .github/workflows/config_test.go
create mode 100644 .github/workflows/defaults.go
create mode 100644 .github/workflows/doc.go
create mode 100644 .github/workflows/endpoints.go
create mode 100644 .github/workflows/errors.go
create mode 100644 .github/workflows/full-node-ansible.md
create mode 100644 .github/workflows/full-node-binaries.md
create mode 100644 .github/workflows/full-node-docker.md
create mode 100644 .github/workflows/full-node-gcp.md
create mode 100644 .github/workflows/full-node-packages.md
create mode 100644 .github/workflows/full-node-system-requirements.md
create mode 100644 .github/workflows/jwt_auth.go
create mode 100644 .github/workflows/jwt_handler.go
create mode 100644 .github/workflows/lifecycle.go
create mode 100644 .github/workflows/main.go
create mode 100644 .github/workflows/node.go
create mode 100644 .github/workflows/node_auth_test.go
create mode 100644 .github/workflows/node_example_test.go
create mode 100644 .github/workflows/node_test.go
create mode 100644 .github/workflows/rpcstack.go
create mode 100644 .github/workflows/rpcstack_test.go
create mode 100644 .github/workflows/utils_test.go
diff --git a/.github/workflows/api.go b/.github/workflows/api.go
new file mode 100644
index 0000000..f81f394
--- /dev/null
+++ b/.github/workflows/api.go
@@ -0,0 +1,337 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package node
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/internal/debug"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// apis returns the collection of built-in RPC APIs.
+func (n *Node) apis() []rpc.API {
+ return []rpc.API{
+ {
+ Namespace: "admin",
+ Service: &adminAPI{n},
+ }, {
+ Namespace: "debug",
+ Service: debug.Handler,
+ }, {
+ Namespace: "web3",
+ Service: &web3API{n},
+ },
+ }
+}
+
+// adminAPI is the collection of administrative API methods exposed over
+// both secure and unsecure RPC channels.
+type adminAPI struct {
+ node *Node // Node interfaced by this API
+}
+
+// AddPeer requests connecting to a remote node, and also maintaining the new
+// connection at all times, even reconnecting if it is lost.
+func (api *adminAPI) AddPeer(url string) (bool, error) {
+ // Make sure the server is running, fail otherwise
+ server := api.node.Server()
+ if server == nil {
+ return false, ErrNodeStopped
+ }
+ // Try to add the url as a static peer and return
+ node, err := enode.Parse(enode.ValidSchemes, url)
+ if err != nil {
+ return false, fmt.Errorf("invalid enode: %v", err)
+ }
+ server.AddPeer(node)
+ return true, nil
+}
+
+// RemovePeer disconnects from a remote node if the connection exists
+func (api *adminAPI) RemovePeer(url string) (bool, error) {
+ // Make sure the server is running, fail otherwise
+ server := api.node.Server()
+ if server == nil {
+ return false, ErrNodeStopped
+ }
+ // Try to remove the url as a static peer and return
+ node, err := enode.Parse(enode.ValidSchemes, url)
+ if err != nil {
+ return false, fmt.Errorf("invalid enode: %v", err)
+ }
+ server.RemovePeer(node)
+ return true, nil
+}
+
+// AddTrustedPeer allows a remote node to always connect, even if slots are full
+func (api *adminAPI) AddTrustedPeer(url string) (bool, error) {
+ // Make sure the server is running, fail otherwise
+ server := api.node.Server()
+ if server == nil {
+ return false, ErrNodeStopped
+ }
+ node, err := enode.Parse(enode.ValidSchemes, url)
+ if err != nil {
+ return false, fmt.Errorf("invalid enode: %v", err)
+ }
+ server.AddTrustedPeer(node)
+ return true, nil
+}
+
+// RemoveTrustedPeer removes a remote node from the trusted peer set, but it
+// does not disconnect it automatically.
+func (api *adminAPI) RemoveTrustedPeer(url string) (bool, error) {
+ // Make sure the server is running, fail otherwise
+ server := api.node.Server()
+ if server == nil {
+ return false, ErrNodeStopped
+ }
+ node, err := enode.Parse(enode.ValidSchemes, url)
+ if err != nil {
+ return false, fmt.Errorf("invalid enode: %v", err)
+ }
+ server.RemoveTrustedPeer(node)
+ return true, nil
+}
+
+// PeerEvents creates an RPC subscription which receives peer events from the
+// node's p2p.Server
+func (api *adminAPI) PeerEvents(ctx context.Context) (*rpc.Subscription, error) {
+ // Make sure the server is running, fail otherwise
+ server := api.node.Server()
+ if server == nil {
+ return nil, ErrNodeStopped
+ }
+
+ // Create the subscription
+ notifier, supported := rpc.NotifierFromContext(ctx)
+ if !supported {
+ return nil, rpc.ErrNotificationsUnsupported
+ }
+ rpcSub := notifier.CreateSubscription()
+
+ go func() {
+ events := make(chan *p2p.PeerEvent)
+ sub := server.SubscribeEvents(events)
+ defer sub.Unsubscribe()
+
+ for {
+ select {
+ case event := <-events:
+ notifier.Notify(rpcSub.ID, event)
+ case <-sub.Err():
+ return
+ case <-rpcSub.Err():
+ return
+ case <-notifier.Closed():
+ return
+ }
+ }
+ }()
+
+ return rpcSub, nil
+}
+
+// StartHTTP starts the HTTP RPC API server.
+func (api *adminAPI) StartHTTP(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) {
+ api.node.lock.Lock()
+ defer api.node.lock.Unlock()
+
+ // Determine host and port.
+ if host == nil {
+ h := DefaultHTTPHost
+ if api.node.config.HTTPHost != "" {
+ h = api.node.config.HTTPHost
+ }
+ host = &h
+ }
+ if port == nil {
+ port = &api.node.config.HTTPPort
+ }
+
+ // Determine config.
+ config := httpConfig{
+ CorsAllowedOrigins: api.node.config.HTTPCors,
+ Vhosts: api.node.config.HTTPVirtualHosts,
+ Modules: api.node.config.HTTPModules,
+ rpcEndpointConfig: rpcEndpointConfig{
+ batchItemLimit: api.node.config.BatchRequestLimit,
+ batchResponseSizeLimit: api.node.config.BatchResponseMaxSize,
+ },
+ }
+ if cors != nil {
+ config.CorsAllowedOrigins = nil
+ for _, origin := range strings.Split(*cors, ",") {
+ config.CorsAllowedOrigins = append(config.CorsAllowedOrigins, strings.TrimSpace(origin))
+ }
+ }
+ if vhosts != nil {
+ config.Vhosts = nil
+ for _, vhost := range strings.Split(*host, ",") {
+ config.Vhosts = append(config.Vhosts, strings.TrimSpace(vhost))
+ }
+ }
+ if apis != nil {
+ config.Modules = nil
+ for _, m := range strings.Split(*apis, ",") {
+ config.Modules = append(config.Modules, strings.TrimSpace(m))
+ }
+ }
+
+ if err := api.node.http.setListenAddr(*host, *port); err != nil {
+ return false, err
+ }
+ if err := api.node.http.enableRPC(api.node.rpcAPIs, config); err != nil {
+ return false, err
+ }
+ if err := api.node.http.start(); err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+// StartRPC starts the HTTP RPC API server.
+// Deprecated: use StartHTTP instead.
+func (api *adminAPI) StartRPC(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) {
+ log.Warn("Deprecation warning", "method", "admin.StartRPC", "use-instead", "admin.StartHTTP")
+ return api.StartHTTP(host, port, cors, apis, vhosts)
+}
+
+// StopHTTP shuts down the HTTP server.
+func (api *adminAPI) StopHTTP() (bool, error) {
+ api.node.http.stop()
+ return true, nil
+}
+
+// StopRPC shuts down the HTTP server.
+// Deprecated: use StopHTTP instead.
+func (api *adminAPI) StopRPC() (bool, error) {
+ log.Warn("Deprecation warning", "method", "admin.StopRPC", "use-instead", "admin.StopHTTP")
+ return api.StopHTTP()
+}
+
+// StartWS starts the websocket RPC API server.
+func (api *adminAPI) StartWS(host *string, port *int, allowedOrigins *string, apis *string) (bool, error) {
+ api.node.lock.Lock()
+ defer api.node.lock.Unlock()
+
+ // Determine host and port.
+ if host == nil {
+ h := DefaultWSHost
+ if api.node.config.WSHost != "" {
+ h = api.node.config.WSHost
+ }
+ host = &h
+ }
+ if port == nil {
+ port = &api.node.config.WSPort
+ }
+
+ // Determine config.
+ config := wsConfig{
+ Modules: api.node.config.WSModules,
+ Origins: api.node.config.WSOrigins,
+ // ExposeAll: api.node.config.WSExposeAll,
+ rpcEndpointConfig: rpcEndpointConfig{
+ batchItemLimit: api.node.config.BatchRequestLimit,
+ batchResponseSizeLimit: api.node.config.BatchResponseMaxSize,
+ },
+ }
+ if apis != nil {
+ config.Modules = nil
+ for _, m := range strings.Split(*apis, ",") {
+ config.Modules = append(config.Modules, strings.TrimSpace(m))
+ }
+ }
+ if allowedOrigins != nil {
+ config.Origins = nil
+ for _, origin := range strings.Split(*allowedOrigins, ",") {
+ config.Origins = append(config.Origins, strings.TrimSpace(origin))
+ }
+ }
+
+ // Enable WebSocket on the server.
+ server := api.node.wsServerForPort(*port, false)
+ if err := server.setListenAddr(*host, *port); err != nil {
+ return false, err
+ }
+ openApis, _ := api.node.getAPIs()
+ if err := server.enableWS(openApis, config); err != nil {
+ return false, err
+ }
+ if err := server.start(); err != nil {
+ return false, err
+ }
+ api.node.http.log.Info("WebSocket endpoint opened", "url", api.node.WSEndpoint())
+ return true, nil
+}
+
+// StopWS terminates all WebSocket servers.
+func (api *adminAPI) StopWS() (bool, error) {
+ api.node.http.stopWS()
+ api.node.ws.stop()
+ return true, nil
+}
+
+// Peers retrieves all the information we know about each individual peer at the
+// protocol granularity.
+func (api *adminAPI) Peers() ([]*p2p.PeerInfo, error) {
+ server := api.node.Server()
+ if server == nil {
+ return nil, ErrNodeStopped
+ }
+ return server.PeersInfo(), nil
+}
+
+// NodeInfo retrieves all the information we know about the host node at the
+// protocol granularity.
+func (api *adminAPI) NodeInfo() (*p2p.NodeInfo, error) {
+ server := api.node.Server()
+ if server == nil {
+ return nil, ErrNodeStopped
+ }
+ return server.NodeInfo(), nil
+}
+
+// Datadir retrieves the current data directory the node is using.
+func (api *adminAPI) Datadir() string {
+ return api.node.DataDir()
+}
+
+// web3API offers helper utils
+type web3API struct {
+ stack *Node
+}
+
+// ClientVersion returns the node name
+func (s *web3API) ClientVersion() string {
+ return s.stack.Server().Name
+}
+
+// Sha3 applies the ethereum sha3 implementation on the input.
+// It assumes the input is hex encoded.
+func (s *web3API) Sha3(input hexutil.Bytes) hexutil.Bytes {
+ return crypto.Keccak256(input)
+}
diff --git a/.github/workflows/api_test.go b/.github/workflows/api_test.go
new file mode 100644
index 0000000..8761c48
--- /dev/null
+++ b/.github/workflows/api_test.go
@@ -0,0 +1,355 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package node
+
+import (
+ "bytes"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/rpc"
+ "github.com/stretchr/testify/assert"
+)
+
+// This test uses the admin_startRPC and admin_startWS APIs,
+// checking whether the HTTP server is started correctly.
+func TestStartRPC(t *testing.T) {
+ type test struct {
+ name string
+ cfg Config
+ fn func(*testing.T, *Node, *adminAPI)
+
+ // Checks. These run after the node is configured and all API calls have been made.
+ wantReachable bool // whether the HTTP server should be reachable at all
+ wantHandlers bool // whether RegisterHandler handlers should be accessible
+ wantRPC bool // whether JSON-RPC/HTTP should be accessible
+ wantWS bool // whether JSON-RPC/WS should be accessible
+ }
+
+ tests := []test{
+ {
+ name: "all off",
+ cfg: Config{},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ },
+ wantReachable: false,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: false,
+ },
+ {
+ name: "rpc enabled through config",
+ cfg: Config{HTTPHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ },
+ wantReachable: true,
+ wantHandlers: true,
+ wantRPC: true,
+ wantWS: false,
+ },
+ {
+ name: "rpc enabled through API",
+ cfg: Config{},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StartHTTP(sp("127.0.0.1"), ip(0), nil, nil, nil)
+ assert.NoError(t, err)
+ },
+ wantReachable: true,
+ wantHandlers: true,
+ wantRPC: true,
+ wantWS: false,
+ },
+ {
+ name: "rpc start again after failure",
+ cfg: Config{},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ // Listen on a random port.
+ listener, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("can't listen:", err)
+ }
+ defer listener.Close()
+ port := listener.Addr().(*net.TCPAddr).Port
+
+ // Now try to start RPC on that port. This should fail.
+ _, err = api.StartHTTP(sp("127.0.0.1"), ip(port), nil, nil, nil)
+ if err == nil {
+ t.Fatal("StartHTTP should have failed on port", port)
+ }
+
+ // Try again after unblocking the port. It should work this time.
+ listener.Close()
+ _, err = api.StartHTTP(sp("127.0.0.1"), ip(port), nil, nil, nil)
+ assert.NoError(t, err)
+ },
+ wantReachable: true,
+ wantHandlers: true,
+ wantRPC: true,
+ wantWS: false,
+ },
+ {
+ name: "rpc stopped through API",
+ cfg: Config{HTTPHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StopHTTP()
+ assert.NoError(t, err)
+ },
+ wantReachable: false,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: false,
+ },
+ {
+ name: "rpc stopped twice",
+ cfg: Config{HTTPHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StopHTTP()
+ assert.NoError(t, err)
+
+ _, err = api.StopHTTP()
+ assert.NoError(t, err)
+ },
+ wantReachable: false,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: false,
+ },
+ {
+ name: "ws enabled through config",
+ cfg: Config{WSHost: "127.0.0.1"},
+ wantReachable: true,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: true,
+ },
+ {
+ name: "ws enabled through API",
+ cfg: Config{},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StartWS(sp("127.0.0.1"), ip(0), nil, nil)
+ assert.NoError(t, err)
+ },
+ wantReachable: true,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: true,
+ },
+ {
+ name: "ws stopped through API",
+ cfg: Config{WSHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StopWS()
+ assert.NoError(t, err)
+ },
+ wantReachable: false,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: false,
+ },
+ {
+ name: "ws stopped twice",
+ cfg: Config{WSHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StopWS()
+ assert.NoError(t, err)
+
+ _, err = api.StopWS()
+ assert.NoError(t, err)
+ },
+ wantReachable: false,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: false,
+ },
+ {
+ name: "ws enabled after RPC",
+ cfg: Config{HTTPHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ wsport := n.http.port
+ _, err := api.StartWS(sp("127.0.0.1"), ip(wsport), nil, nil)
+ assert.NoError(t, err)
+ },
+ wantReachable: true,
+ wantHandlers: true,
+ wantRPC: true,
+ wantWS: true,
+ },
+ {
+ name: "ws enabled after RPC then stopped",
+ cfg: Config{HTTPHost: "127.0.0.1"},
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ wsport := n.http.port
+ _, err := api.StartWS(sp("127.0.0.1"), ip(wsport), nil, nil)
+ assert.NoError(t, err)
+
+ _, err = api.StopWS()
+ assert.NoError(t, err)
+ },
+ wantReachable: true,
+ wantHandlers: true,
+ wantRPC: true,
+ wantWS: false,
+ },
+ {
+ name: "rpc stopped with ws enabled",
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StartHTTP(sp("127.0.0.1"), ip(0), nil, nil, nil)
+ assert.NoError(t, err)
+
+ wsport := n.http.port
+ _, err = api.StartWS(sp("127.0.0.1"), ip(wsport), nil, nil)
+ assert.NoError(t, err)
+
+ _, err = api.StopHTTP()
+ assert.NoError(t, err)
+ },
+ wantReachable: false,
+ wantHandlers: false,
+ wantRPC: false,
+ wantWS: false,
+ },
+ {
+ name: "rpc enabled after ws",
+ fn: func(t *testing.T, n *Node, api *adminAPI) {
+ _, err := api.StartWS(sp("127.0.0.1"), ip(0), nil, nil)
+ assert.NoError(t, err)
+
+ wsport := n.http.port
+ _, err = api.StartHTTP(sp("127.0.0.1"), ip(wsport), nil, nil, nil)
+ assert.NoError(t, err)
+ },
+ wantReachable: true,
+ wantHandlers: true,
+ wantRPC: true,
+ wantWS: true,
+ },
+ }
+
+ for _, test := range tests {
+ test := test
+ t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
+
+ // Apply some sane defaults.
+ config := test.cfg
+ // config.Logger = testlog.Logger(t, log.LvlDebug)
+ config.P2P.NoDiscovery = true
+ if config.HTTPTimeouts == (rpc.HTTPTimeouts{}) {
+ config.HTTPTimeouts = rpc.DefaultHTTPTimeouts
+ }
+
+ // Create Node.
+ stack, err := New(&config)
+ if err != nil {
+ t.Fatal("can't create node:", err)
+ }
+ defer stack.Close()
+
+ // Register the test handler.
+ stack.RegisterHandler("test", "/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("OK"))
+ }))
+
+ if err := stack.Start(); err != nil {
+ t.Fatal("can't start node:", err)
+ }
+
+ // Run the API call hook.
+ if test.fn != nil {
+ test.fn(t, stack, &adminAPI{stack})
+ }
+
+ // Check if the HTTP endpoints are available.
+ baseURL := stack.HTTPEndpoint()
+ reachable := checkReachable(baseURL)
+ handlersAvailable := checkBodyOK(baseURL + "/test")
+ rpcAvailable := checkRPC(baseURL)
+ wsAvailable := checkRPC(strings.Replace(baseURL, "http://", "ws://", 1))
+ if reachable != test.wantReachable {
+ t.Errorf("HTTP server is %sreachable, want it %sreachable", not(reachable), not(test.wantReachable))
+ }
+ if handlersAvailable != test.wantHandlers {
+ t.Errorf("RegisterHandler handlers %savailable, want them %savailable", not(handlersAvailable), not(test.wantHandlers))
+ }
+ if rpcAvailable != test.wantRPC {
+ t.Errorf("HTTP RPC %savailable, want it %savailable", not(rpcAvailable), not(test.wantRPC))
+ }
+ if wsAvailable != test.wantWS {
+ t.Errorf("WS RPC %savailable, want it %savailable", not(wsAvailable), not(test.wantWS))
+ }
+ })
+ }
+}
+
+// checkReachable checks if the TCP endpoint in rawurl is open.
+func checkReachable(rawurl string) bool {
+ u, err := url.Parse(rawurl)
+ if err != nil {
+ panic(err)
+ }
+ conn, err := net.Dial("tcp", u.Host)
+ if err != nil {
+ return false
+ }
+ conn.Close()
+ return true
+}
+
+// checkBodyOK checks whether the given HTTP URL responds with 200 OK and body "OK".
+func checkBodyOK(url string) bool {
+ resp, err := http.Get(url)
+ if err != nil {
+ return false
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != 200 {
+ return false
+ }
+ buf := make([]byte, 2)
+ if _, err = io.ReadFull(resp.Body, buf); err != nil {
+ return false
+ }
+ return bytes.Equal(buf, []byte("OK"))
+}
+
+// checkRPC checks whether JSON-RPC works against the given URL.
+func checkRPC(url string) bool {
+ c, err := rpc.Dial(url)
+ if err != nil {
+ return false
+ }
+ defer c.Close()
+
+ _, err = c.SupportedModules()
+ return err == nil
+}
+
+// string/int pointer helpers.
+func sp(s string) *string { return &s }
+func ip(i int) *int { return &i }
+
+func not(ok bool) string {
+ if ok {
+ return ""
+ }
+ return "not "
+}
diff --git a/.github/workflows/auth0-integration.pdf b/.github/workflows/auth0-integration.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..bcc27a8b8bd89921b4c870366d86de1218cc6cb4
GIT binary patch
literal 83721
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