Skip to content

Commit

Permalink
Merge branch 'main' into rpc-unix
Browse files Browse the repository at this point in the history
  • Loading branch information
Exca-DK committed Dec 19, 2023
2 parents 31cc96c + e9e9a57 commit 4bbbc41
Show file tree
Hide file tree
Showing 15 changed files with 449 additions and 139 deletions.
4 changes: 3 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ updates:
- package-ecosystem: "npm"
directory: "/docs"
schedule:
interval: "weekly"
interval: "monthly"
ignore:
- dependency-name: "*"
25 changes: 19 additions & 6 deletions clients/feeder/feeder.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/juno/starknet"
"github.com/NethermindEth/juno/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type Backoff func(wait time.Duration) time.Duration
Expand All @@ -30,6 +32,7 @@ type Client struct {
minWait time.Duration
log utils.SimpleLogger
userAgent string
apiKey string
listener EventListener
}

Expand Down Expand Up @@ -73,6 +76,11 @@ func (c *Client) WithTimeout(t time.Duration) *Client {
return c
}

func (c *Client) WithAPIKey(key string) *Client {
c.apiKey = key
return c
}

func ExponentialBackoff(wait time.Duration) time.Duration {
return wait * 2
}
Expand All @@ -83,11 +91,12 @@ func NopBackoff(d time.Duration) time.Duration {

// NewTestClient returns a client and a function to close a test server.
func NewTestClient(t *testing.T, network utils.Network) *Client {
srv := newTestServer(network)
srv := newTestServer(t, network)
t.Cleanup(srv.Close)
ua := "Juno/v0.0.1-test Starknet Implementation"
apiKey := "API_KEY"

c := NewClient(srv.URL).WithBackoff(NopBackoff).WithMaxRetries(0).WithUserAgent(ua)
c := NewClient(srv.URL).WithBackoff(NopBackoff).WithMaxRetries(0).WithUserAgent(ua).WithAPIKey(apiKey)
c.client = &http.Client{
Transport: &http.Transport{
// On macOS tests often fail with the following error:
Expand All @@ -106,18 +115,19 @@ func NewTestClient(t *testing.T, network utils.Network) *Client {
return c
}

func newTestServer(network utils.Network) *httptest.Server {
func newTestServer(t *testing.T, network utils.Network) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
queryMap, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

assert.Equal(t, []string{"API_KEY"}, r.Header["X-Throttling-Bypass"])
assert.Equal(t, []string{"Juno/v0.0.1-test Starknet Implementation"}, r.Header["User-Agent"])

wd, err := os.Getwd()
if err != nil {
panic(err)
}
require.NoError(t, err)

base := wd[:strings.LastIndex(wd, "juno")+4]
queryArg := ""
Expand Down Expand Up @@ -231,6 +241,9 @@ func (c *Client) get(ctx context.Context, queryURL string) (io.ReadCloser, error
if c.userAgent != "" {
req.Header.Set("User-Agent", c.userAgent)
}
if c.apiKey != "" {
req.Header.Set("X-Throttling-Bypass", c.apiKey)
}

reqTimer := time.Now()
res, err = c.client.Do(req)
Expand Down
20 changes: 17 additions & 3 deletions clients/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/juno/utils"
"github.com/stretchr/testify/assert"
)

var (
Expand All @@ -40,25 +41,35 @@ type Client struct {
timeout time.Duration
log utils.SimpleLogger
userAgent string
apiKey string
}

func (c *Client) WithUserAgent(ua string) *Client {
c.userAgent = ua
return c
}

func (c *Client) WithAPIKey(key string) *Client {
c.apiKey = key
return c
}

// NewTestClient returns a client and a function to close a test server.
func NewTestClient(t *testing.T) *Client {
srv := newTestServer()
srv := newTestServer(t)
ua := "Juno/v0.0.1-test Starknet Implementation"
apiKey := "API_KEY"
t.Cleanup(srv.Close)

return NewClient(srv.URL, utils.NewNopZapLogger()).WithUserAgent(ua)
return NewClient(srv.URL, utils.NewNopZapLogger()).WithUserAgent(ua).WithAPIKey(apiKey)
}

func newTestServer() *httptest.Server {
func newTestServer(t *testing.T) *httptest.Server {
// As this is a test sever we are mimic response for one good and one bad request.
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, []string{"API_KEY"}, r.Header["X-Throttling-Bypass"])
assert.Equal(t, []string{"Juno/v0.0.1-test Starknet Implementation"}, r.Header["User-Agent"])

b, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
Expand Down Expand Up @@ -142,6 +153,9 @@ func (c *Client) doPost(ctx context.Context, url string, data any) (*http.Respon
if c.userAgent != "" {
req.Header.Set("User-Agent", c.userAgent)
}
if c.apiKey != "" {
req.Header.Set("X-Throttling-Bypass", c.apiKey)
}
return c.client.Do(req)
}

Expand Down
8 changes: 8 additions & 0 deletions cmd/juno/juno.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os/signal"
"path/filepath"
"runtime"
"strings"
"syscall"
"time"

Expand Down Expand Up @@ -64,6 +65,7 @@ const (
remoteDBF = "remote-db"
rpcMaxBlockScanF = "rpc-max-block-scan"
dbCacheSizeF = "db-cache-size"
gwAPIKeyF = "gw-api-key" //nolint: gosec

defaultConfig = ""
defaulHost = "localhost"
Expand All @@ -87,6 +89,7 @@ const (
defaultRemoteDB = ""
defaultRPCMaxBlockScan = math.MaxUint
defaultCacheSizeMb = 8
defaultGwAPIKey = ""

configFlagUsage = "The yaml configuration file."
logLevelFlagUsage = "Options: debug, info, warn, error."
Expand Down Expand Up @@ -121,6 +124,7 @@ const (
remoteDBUsage = "gRPC URL of a remote Juno node"
rpcMaxBlockScanUsage = "Maximum number of blocks scanned in single starknet_getEvents call"
dbCacheSizeUsage = "Determines the amount of memory (in megabytes) allocated for caching data in the database."
gwAPIKeyUsage = "API key for gateway endpoints to avoid throttling" //nolint: gosec
)

var Version string
Expand Down Expand Up @@ -191,6 +195,9 @@ func NewCmd(config *node.Config, run func(*cobra.Command, []string) error) *cobr
}
}

v.AutomaticEnv()
v.SetEnvPrefix("JUNO")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
if err := v.BindPFlags(cmd.Flags()); err != nil {
return nil
}
Expand Down Expand Up @@ -248,6 +255,7 @@ func NewCmd(config *node.Config, run func(*cobra.Command, []string) error) *cobr
junoCmd.Flags().String(remoteDBF, defaultRemoteDB, remoteDBUsage)
junoCmd.Flags().Uint(rpcMaxBlockScanF, defaultRPCMaxBlockScan, rpcMaxBlockScanUsage)
junoCmd.Flags().Uint(dbCacheSizeF, defaultCacheSizeMb, dbCacheSizeUsage)
junoCmd.Flags().String(gwAPIKeyF, defaultGwAPIKey, gwAPIKeyUsage)

return junoCmd
}
104 changes: 104 additions & 0 deletions cmd/juno/juno_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func TestConfigPrecedence(t *testing.T) {
cfgFileContents string
expectErr bool
inputArgs []string
env []string
expectedConfig *node.Config
}{
"default config with no flags": {
Expand Down Expand Up @@ -423,6 +424,96 @@ network: goerli
DBCacheSize: defaultMaxCacheSize,
},
},
"only set env variables": {
env: []string{"JUNO_HTTP_PORT", "8080", "JUNO_WS", "true", "JUNO_HTTP_HOST", "0.0.0.0"},
expectedConfig: &node.Config{
LogLevel: defaultLogLevel,
HTTP: defaultHTTP,
HTTPHost: "0.0.0.0",
HTTPPort: 8080,
Websocket: true,
WebsocketHost: defaultHost,
WebsocketPort: defaultWSPort,
GRPC: defaultGRPC,
GRPCHost: defaultHost,
GRPCPort: defaultGRPCPort,
Metrics: defaultMetrics,
MetricsHost: defaultHost,
MetricsPort: defaultMetricsPort,
DatabasePath: defaultDBPath,
Network: defaultNetwork,
Pprof: defaultPprof,
PprofHost: defaultHost,
PprofPort: defaultPprofPort,
Colour: defaultColour,
PendingPollInterval: defaultPendingPollInterval,
MaxVMs: defaultMaxVMs,
MaxVMQueue: 2 * defaultMaxVMs,
RPCMaxBlockScan: defaultRPCMaxBlockScan,
DBCacheSize: defaultMaxCacheSize,
},
},
"some setting set in both env variables and flags": {
env: []string{"JUNO_DB_PATH", "/home/env/.juno"},
inputArgs: []string{"--db-path", "/home/flag/.juno"},
expectedConfig: &node.Config{
LogLevel: defaultLogLevel,
HTTP: defaultHTTP,
HTTPHost: defaultHost,
HTTPPort: defaultHTTPPort,
Websocket: defaultWS,
WebsocketHost: defaultHost,
WebsocketPort: defaultWSPort,
GRPC: defaultGRPC,
GRPCHost: defaultHost,
GRPCPort: defaultGRPCPort,
Metrics: defaultMetrics,
MetricsHost: defaultHost,
MetricsPort: defaultMetricsPort,
DatabasePath: "/home/flag/.juno",
Network: defaultNetwork,
Pprof: defaultPprof,
PprofHost: defaultHost,
PprofPort: defaultPprofPort,
Colour: defaultColour,
PendingPollInterval: defaultPendingPollInterval,
MaxVMs: defaultMaxVMs,
MaxVMQueue: 2 * defaultMaxVMs,
RPCMaxBlockScan: defaultRPCMaxBlockScan,
DBCacheSize: defaultMaxCacheSize,
},
},
"some setting set in both env variables and config file": {
cfgFileContents: `db-path: /home/file/.juno`,
env: []string{"JUNO_DB_PATH", "/home/env/.juno", "JUNO_GW_API_KEY", "apikey"},
expectedConfig: &node.Config{
LogLevel: defaultLogLevel,
HTTP: defaultHTTP,
HTTPHost: defaultHost,
HTTPPort: defaultHTTPPort,
Websocket: defaultWS,
WebsocketHost: defaultHost,
WebsocketPort: defaultWSPort,
GRPC: defaultGRPC,
GRPCHost: defaultHost,
GRPCPort: defaultGRPCPort,
Metrics: defaultMetrics,
MetricsHost: defaultHost,
MetricsPort: defaultMetricsPort,
DatabasePath: "/home/env/.juno",
Network: defaultNetwork,
Pprof: defaultPprof,
PprofHost: defaultHost,
PprofPort: defaultPprofPort,
Colour: defaultColour,
PendingPollInterval: defaultPendingPollInterval,
MaxVMs: defaultMaxVMs,
MaxVMQueue: 2 * defaultMaxVMs,
RPCMaxBlockScan: defaultRPCMaxBlockScan,
DBCacheSize: defaultMaxCacheSize,
GatewayAPIKey: "apikey",
},
},
}

for name, tc := range tests {
Expand All @@ -432,6 +523,14 @@ network: goerli
tc.inputArgs = append(tc.inputArgs, "--config", fileN)
}

require.True(t, len(tc.env)%2 == 0, "The number of env variables should be an even number")

if len(tc.env) > 0 {
for i := 0; i < len(tc.env)/2; i++ {
os.Setenv(tc.env[2*i], tc.env[2*i+1])
}
}

config := new(node.Config)
cmd := juno.NewCmd(config, func(_ *cobra.Command, _ []string) error { return nil })
cmd.SetArgs(tc.inputArgs)
Expand All @@ -444,6 +543,11 @@ network: goerli
require.NoError(t, err)

assert.Equal(t, tc.expectedConfig, config)
if len(tc.env) > 0 {
for i := 0; i < len(tc.env)/2; i++ {
os.Unsetenv(tc.env[2*i])
}
}
})
}
}
Expand Down
73 changes: 73 additions & 0 deletions core/crypto/ecdsa_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package crypto_test

import (
"testing"

"github.com/NethermindEth/juno/core/crypto"
"github.com/NethermindEth/juno/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestVerify(t *testing.T) {
tests := map[string]struct {
key string
msg string
sigR string
sigS string
result bool
errorMsg string
}{
"success": {
key: "0x01ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca",
msg: "0x0000000000000000000000000000000000000000000000000000000000000002",
sigR: "0x0411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20",
sigS: "0x0405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b",
result: true,
},
"fail": {
key: "0x077a4b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43",
msg: "0x0397e76d1667c4454bfb83514e120583af836f8e32a516765497823eabe16a3f",
sigR: "0x0173fd03d8b008ee7432977ac27d1e9d1a1f6c98b1a2f05fa84a21c84c44e882",
sigS: "0x01f2c44a7798f55192f153b4c48ea5c1241fbb69e6132cc8a0da9c5b62a4286e",
},
"invalid key": {
key: "0x03ee9bffffffffff26ffffffff60ffffffffffffffffffffffffffff004accff",
msg: "0x0000000000000000000000000000000000000000000000000000000000000002",
sigR: "0x0411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20",
sigS: "0x0405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b",
errorMsg: "not a valid public key",
},
}
for desc, test := range tests {
t.Run(desc, func(t *testing.T) {
signature := crypto.Signature{
R: *utils.HexToFelt(t, test.sigR),
S: *utils.HexToFelt(t, test.sigS),
}
msg := utils.HexToFelt(t, test.msg)
publicKey := crypto.NewPublicKey(utils.HexToFelt(t, test.key))

res, err := publicKey.Verify(&signature, msg)
assert.Equal(t, test.result, res)
if test.errorMsg != "" {
assert.ErrorContains(t, err, test.errorMsg)
}
})
}
}

func BenchmarkVerify(b *testing.B) {
signature := crypto.Signature{
R: *utils.HexToFelt(b, "0x0411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20"),
S: *utils.HexToFelt(b, "0x0405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b"),
}
msg := utils.HexToFelt(b, "0x0000000000000000000000000000000000000000000000000000000000000002")
publicKey := crypto.NewPublicKey(utils.HexToFelt(b, "0x01ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca"))

b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := publicKey.Verify(&signature, msg)
require.NoError(b, err)
}
}
Loading

0 comments on commit 4bbbc41

Please sign in to comment.