Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolves IP Lookups #270 #313

Merged
69 commits merged into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
00cd561
retrive public ip in prod
apoorv-2204 May 11, 2022
776a0f2
Amend method name publicip to is_public_ip
apoorv-2204 May 11, 2022
6e0a771
improve method is_public_ip
apoorv-2204 May 11, 2022
9a4b541
Simplify logic
apoorv-2204 May 11, 2022
7450cb9
remove private ip from production
apoorv-2204 May 12, 2022
71cb2f6
remove static alias
apoorv-2204 May 12, 2022
e10dba3
add validate_ip ? modify logic
apoorv-2204 May 12, 2022
725087b
restore defaults
apoorv-2204 May 13, 2022
71ed0a9
add simple solution
apoorv-2204 May 13, 2022
5e13cb6
remove mining_pending_txn Module parameters || add validate ip in Net…
apoorv-2204 May 13, 2022
8f99f76
add mock tests
apoorv-2204 May 13, 2022
49a61aa
redo add mock tests for iplookup
apoorv-2204 May 13, 2022
a44a77e
remove unused aliases|| modify config/test.exs
apoorv-2204 May 13, 2022
46d7e68
improve code
apoorv-2204 May 16, 2022
19be245
mix format
apoorv-2204 May 16, 2022
5593675
rollback config file changes
apoorv-2204 May 17, 2022
337ba4f
trying to add default_impl
apoorv-2204 May 18, 2022
a8a896c
refactor to improve code feasiblity
apoorv-2204 May 18, 2022
b76fb61
add changes related to refactor
apoorv-2204 May 18, 2022
8b94f45
correct typos || refactor Iplookuptests.ex
apoorv-2204 May 18, 2022
ec896da
Archethic.Networking.IPLookup.NAT is not a behaviour
apoorv-2204 May 18, 2022
6d6028b
use knigge to refactor for test feasiblity
apoorv-2204 May 18, 2022
c00bc82
remove unused import mox from trasaction_controller_test
apoorv-2204 May 18, 2022
373ed33
add kenige.verify
apoorv-2204 May 23, 2022
ea1527d
add mix knigge
apoorv-2204 May 23, 2022
5621518
simplify iplookuptest.exs
apoorv-2204 May 23, 2022
5361ba1
modify production.exs for Lookup And PublicGateway modules
apoorv-2204 May 23, 2022
e801908
add mix prod alias
apoorv-2204 May 23, 2022
3a7b5fd
revert prod.exs
apoorv-2204 May 23, 2022
25c27d8
simplifiy fallback
apoorv-2204 May 23, 2022
190d7ac
add prod alias with no tpm
apoorv-2204 May 23, 2022
4b8e28f
add localdiscovery in iplookup
apoorv-2204 May 23, 2022
7828c4e
temp
apoorv-2204 May 23, 2022
8103a06
Revert "temp"
apoorv-2204 May 23, 2022
23e7ff3
mess complete mess
apoorv-2204 May 23, 2022
914e9db
revert to "temp"
apoorv-2204 May 23, 2022
546bf0b
Revert "add localdiscovery in iplookup"
apoorv-2204 May 23, 2022
4c40458
any another way to address module patter mathching
apoorv-2204 May 24, 2022
5dcf619
simplifiy tests
apoorv-2204 May 24, 2022
724f7e3
improve test naming
apoorv-2204 May 24, 2022
f9ab92b
add guidlines
apoorv-2204 May 24, 2022
3fb49bc
format dev-guidlines
apoorv-2204 May 24, 2022
2fbe208
correct dev.exs
apoorv-2204 May 24, 2022
2251603
format dev.exs
apoorv-2204 May 24, 2022
a5732fd
modify params
apoorv-2204 May 24, 2022
eb90f96
provide new abstraction
apoorv-2204 May 25, 2022
f7f9697
remove patch , kept for history
apoorv-2204 May 25, 2022
41f6748
refactor code for mock test feasibility
apoorv-2204 May 25, 2022
fcc466e
resolve git hooks
apoorv-2204 May 25, 2022
d0550af
change LocalDiscovery TO NATDiscovery
apoorv-2204 May 25, 2022
9f7a725
correct prod.exs
apoorv-2204 May 25, 2022
de87425
request change p1
apoorv-2204 May 25, 2022
eee1f96
revert the handler
apoorv-2204 May 25, 2022
27f2688
correct tests
apoorv-2204 May 25, 2022
6faabf0
add spec
apoorv-2204 May 25, 2022
bf03e23
correct specs
apoorv-2204 May 25, 2022
d4cced7
remove specs causing dialyzer issues
apoorv-2204 May 25, 2022
389cf53
add {:error, error} return from remote discovery
apoorv-2204 May 25, 2022
a9ac434
resolve fallback in remote discovery
apoorv-2204 May 25, 2022
a53693c
Revert "resolve fallback in remote discovery"
apoorv-2204 May 25, 2022
62d6b04
adopt suggested changes in remote dicovery
apoorv-2204 May 25, 2022
e495db3
resolve {}
apoorv-2204 May 25, 2022
b3de554
requested changes
apoorv-2204 May 27, 2022
90feb3a
correct ipfy to ipify in prod.exs
apoorv-2204 May 27, 2022
3360f8a
amend if else clause instead of case in networking.exs
apoorv-2204 May 27, 2022
904a023
change in sys_env: ipify to remote discovery in prod.exs
apoorv-2204 May 27, 2022
1da9df9
change module_args() to provider()
apoorv-2204 May 27, 2022
d63fa9f
add remote
apoorv-2204 May 27, 2022
1a5c30d
add @type specs and docs
apoorv-2204 May 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ config :git_hooks,
"mix format --check-formatted",
"mix compile --warnings-as-errors",
"mix credo",
"mix knigge.verify",
"mix test --trace",
"mix dialyzer"
]
Expand Down Expand Up @@ -124,6 +125,16 @@ config :archethic, ArchethicWeb.FaucetController,
"3A7B579DBFB7CEBE26293850058F180A65D6A3D2F6964543F5EDE07BEB2EFDA4"
|> Base.decode16!(case: :mixed)

# -----Start-of-Networking-configs-----
apoorv-2204 marked this conversation as resolved.
Show resolved Hide resolved

config :archethic, Archethic.Networking.IPLookup.NATDiscovery,
provider: Archethic.Networking.IPLookup.NATDiscovery.UPnPv1

config :archethic, Archethic.Networking.IPLookup.RemoteDiscovery,
provider: Archethic.Networking.IPLookup.RemoteDiscovery.IPIFY

# -----End-of-Networking-configs ------

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
import_config("#{Mix.env()}.exs")
6 changes: 6 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,19 @@ config :archethic, Archethic.OracleChain.Scheduler,
# Aggregate chain at the 50th second
summary_interval: "0 * * * * *"

# -----Start-of-Networking-dev-configs-----
config :archethic, Archethic.Networking,
validate_node_ip: System.get_env("ARCHETHIC_NODE_IP_VALIDATION", "false") == "true"

config :archethic, Archethic.Networking.IPLookup, Archethic.Networking.IPLookup.Static

config :archethic, Archethic.Networking.IPLookup.Static,
apoorv-2204 marked this conversation as resolved.
Show resolved Hide resolved
hostname: System.get_env("ARCHETHIC_STATIC_IP", "127.0.0.1")

config :archethic, Archethic.Networking.Scheduler, interval: "0 * * * * * *"

# -----end-of-Networking-dev-configs-----

config :archethic, Archethic.Reward.NetworkPoolScheduler,
# At the 30th second
interval: "30 * * * * *"
Expand Down
23 changes: 10 additions & 13 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,22 @@ config :archethic, Archethic.Mining.PendingTransactionValidation,
:software
end)

# -----Start-of-Networking-prod-configs-----

config :archethic, Archethic.Networking,
validate_node_ip: System.get_env("ARCHETHIC_NODE_IP_VALIDATION", "true") == "true"

config :archethic,
Archethic.Networking.IPLookup,
(case(System.get_env("ARCHETHIC_NETWORKING_IMPL", "NAT") |> String.upcase()) do
"NAT" ->
Archethic.Networking.IPLookup.NAT
Archethic.Networking.IPLookup.NATDiscovery

"STATIC" ->
Archethic.Networking.IPLookup.Static

"IPFY" ->
Archethic.Networking.IPLookup.IPIFY
"IPIFY" ->
apoorv-2204 marked this conversation as resolved.
Show resolved Hide resolved
Archethic.Networking.IPLookup.RemoteDiscovery
end)

config :archethic, Archethic.Networking.PortForwarding,
Expand All @@ -169,6 +174,8 @@ config :archethic, Archethic.Networking.PortForwarding,
config :archethic, Archethic.Networking.IPLookup.Static,
apoorv-2204 marked this conversation as resolved.
Show resolved Hide resolved
hostname: System.get_env("ARCHETHIC_STATIC_IP")

# -----end-of-Networking-prod-configs-----

config :archethic, Archethic.Networking.Scheduler,
interval: System.get_env("ARCHETHIC_NETWORKING_UPDATE_SCHEDULER", "0 0 * * * * *")

Expand Down Expand Up @@ -207,16 +214,6 @@ config :archethic, Archethic.P2P.BootstrappingSeeds,
# TODO: define the default list of P2P seeds once the network will be more open to new miners
genesis_seeds: System.get_env("ARCHETHIC_P2P_BOOTSTRAPPING_SEEDS")

config :archethic, Archethic.Mining.PendingTransactionValidation,
validate_node_ip:
(case(System.get_env("ARCHETHIC_NODE_IP_VALIDATION", "true")) do
"true" ->
true

_ ->
false
end)

config :archethic, ArchethicWeb.FaucetController,
enabled: System.get_env("ARCHETHIC_NETWORK_TYPE") == "testnet"

Expand Down
13 changes: 13 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,23 @@ config :archethic, Archethic.OracleChain.Scheduler,

config :archethic, Archethic.OracleChain.Services.UCOPrice, provider: MockUCOPriceProvider

# -----Start-of-Networking-tests-configs-----

config :archethic, Archethic.Networking, validate_node_ip: false

config :archethic, Archethic.Networking.IPLookup, MockIPLookup
config :archethic, Archethic.Networking.IPLookup.Static, MockStatic

# Regardless of default upnpV1 use MockNATDiscovery
config :archethic, Archethic.Networking.IPLookup.NATDiscovery, provider: MockNATDiscovery
# Regardless of default IPIFY use MockRemoteDiscovery
config :archethic, Archethic.Networking.IPLookup.RemoteDiscovery, provider: MockRemoteDiscovery

config :archethic, Archethic.Networking.PortForwarding, MockPortForwarding
config :archethic, Archethic.Networking.Scheduler, enabled: false

# -----End-of-Networking-tests-configs ------

config :archethic, Archethic.P2P.Listener, enabled: false
config :archethic, Archethic.P2P.MemTableLoader, enabled: false
config :archethic, Archethic.P2P.MemTable, enabled: false
Expand Down
39 changes: 15 additions & 24 deletions lib/archethic/mining/pending_transaction_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ defmodule Archethic.Mining.PendingTransactionValidation do
key_certificate,
root_ca_public_key
)},
{:conn, true} <-
{:conn, valid_connection?(ip, port, previous_public_key, should_validate_node_ip?())} do
{:conn, :ok} <-
{:conn, valid_connection(ip, port, previous_public_key)} do
:ok
else
:error ->
Expand All @@ -150,8 +150,12 @@ defmodule Archethic.Mining.PendingTransactionValidation do
{:auth_origin, false} ->
{:error, "Invalid node transaction with invalid key origin"}

{:conn, false} ->
{:error, "Invalid node connection (IP/Port) for the given public key"}
{:conn, {:error, :invalid_ip}} ->
{:error, "Invalid node's IP address"}

{:conn, {:error, :existing_node}} ->
{:error,
"Invalid node connection (IP/Port) for for the given public key - already existing"}
end
end

Expand Down Expand Up @@ -297,29 +301,16 @@ defmodule Archethic.Mining.PendingTransactionValidation do

defp get_first_public_key([], _), do: {:error, :network_issue}

defp valid_connection?(ip, port, previous_public_key, _check_ip? = true) do
with true <- Networking.valid_ip?(ip),
defp valid_connection(ip, port, previous_public_key) do
with :ok <- Networking.validate_ip(ip),
false <- P2P.duplicating_node?(ip, port, previous_public_key) do
true
:ok
else
_ ->
false
end
end

defp valid_connection?(ip, port, previous_public_key, _check_ip? = false) do
case P2P.duplicating_node?(ip, port, previous_public_key) do
false ->
true

true ->
false
end
end
{:error, :existing_node}

defp should_validate_node_ip? do
:archethic
|> Application.get_env(__MODULE__, [])
|> Keyword.get(:validate_node_ip, false)
{:error, :invalid_ip} ->
{:error, :invalid_ip}
end
end
end
19 changes: 19 additions & 0 deletions lib/archethic/networking.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ defmodule Archethic.Networking do
alias __MODULE__.PortForwarding

@ip_validate_regex ~r/(^0\.)|(^127\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)/

def validate_ip(ip, ip_validation? \\ should_validate_node_ip?())
apoorv-2204 marked this conversation as resolved.
Show resolved Hide resolved

def validate_ip(ip, true) do
if valid_ip?(ip) do
:ok
else
{:error, :invalid_ip}
end
end

def validate_ip(_ip, false), do: :ok

@doc """
Provides current host IP address by leveraging the IP lookup provider.

Expand Down Expand Up @@ -63,4 +76,10 @@ defmodule Archethic.Networking do
)
end
end

defp should_validate_node_ip?() do
:archethic
|> Application.get_env(__MODULE__, [])
|> Keyword.get(:validate_node_ip, false)
end
end
39 changes: 20 additions & 19 deletions lib/archethic/networking/ip_lookup.ex
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
defmodule Archethic.Networking.IPLookup do
@moduledoc false

alias __MODULE__.IPIFY
alias __MODULE__.NAT

require Logger

alias Archethic.Networking
alias Archethic.Networking.IPLookup.RemoteDiscovery
alias Archethic.Networking.IPLookup.NATDiscovery

@doc """
Get the node public ip with a fallback capability

For example, using the NAT provider, if the UPnP discovery failed, it switches to the IPIFY to get the external public ip
"""
@spec get_node_ip() :: :inet.ip_address()
def get_node_ip do
provider = get_provider()
def get_node_ip() do
provider = module_args()

ip =
case apply(provider, :get_node_ip, []) do
{:ok, ip} ->
Logger.info("Node IP discovered by #{provider}")
ip

with {:ok, ip} <- provider.get_node_ip(),
:ok <- Networking.validate_ip(ip) do
Logger.info("Node IP discovered by #{provider}")
ip
else
{:error, reason} ->
fallback(provider, reason)
end
Expand All @@ -29,24 +30,24 @@ defmodule Archethic.Networking.IPLookup do
ip
end

defp get_provider do
Application.get_env(:archethic, __MODULE__)
end

defp fallback(NAT, reason) do
Logger.warning("Cannot use NAT IP lookup - #{inspect(reason)}")
Logger.info("Trying IPFY as fallback")
defp fallback(NATDiscovery, reason) do
Logger.warning("Cannot use NATDiscovery: NAT IP lookup - #{inspect(reason)}")
Logger.info("Trying PublicGateway: IPIFY as fallback")

case IPIFY.get_node_ip() do
case RemoteDiscovery.get_node_ip() do
{:ok, ip} ->
ip

{:error, reason} ->
fallback(IPIFY, reason)
fallback(RemoteDiscovery, reason)
end
end

defp fallback(provider, reason) do
raise "Cannot use #{provider} IP lookup - #{inspect(reason)}"
end

defp module_args() do
Application.get_env(:archethic, __MODULE__)
end
end
29 changes: 0 additions & 29 deletions lib/archethic/networking/ip_lookup/nat.ex

This file was deleted.

55 changes: 55 additions & 0 deletions lib/archethic/networking/ip_lookup/nat_discovery.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
defmodule Archethic.Networking.IPLookup.NATDiscovery do
@moduledoc """
Provide abstraction over :natupnp_v1, :natupnp_v2, :natpmp
"""

alias Archethic.Networking.IPLookup.Impl

alias __MODULE__.UPnPv1
alias __MODULE__.UPnPv2
alias __MODULE__.PMP

require Logger

@behaviour Impl
def get_node_ip() do
provider = module_args()
do_get_node_ip(provider)
end

defp do_get_node_ip(provider) do
case provider.get_node_ip() do
{:ok, ip} ->
{:ok, ip}

{:error, reason} ->
Logger.error(
"Cannot use the provider #{provider} for IP Lookup - reason: #{inspect(reason)}"
)

fallback(provider, reason)
end
end

defp fallback(UPnPv1, _reason) do
do_get_node_ip(UPnPv2)
end

defp fallback(UPnPv2, _reason) do
do_get_node_ip(PMP)
end

defp fallback(PMP, reason) do
{:error, reason}
end

defp fallback(_provider, reason) do
{:error, reason}
end

defp module_args() do
apoorv-2204 marked this conversation as resolved.
Show resolved Hide resolved
:archethic
|> Application.get_env(__MODULE__, [])
|> Keyword.get(:provider, UPnPv1)
end
end
14 changes: 14 additions & 0 deletions lib/archethic/networking/ip_lookup/nat_discovery/pmp.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule Archethic.Networking.IPLookup.NATDiscovery.PMP do
@moduledoc false
alias Archethic.Networking.IPLookup.Impl

@behaviour Impl

@impl Impl
def get_node_ip() do
with {:ok, router_ip} <- :natpmp.discover(),
{:ok, ip_chars} <- :natpmp.get_external_address(router_ip) do
:inet.parse_address(ip_chars)
end
end
end
Loading