Skip to content

Commit

Permalink
Add geopatch to node transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Wassim Mansouri committed Nov 24, 2024
1 parent e187ef7 commit 98184eb
Show file tree
Hide file tree
Showing 19 changed files with 415 additions and 54 deletions.
45 changes: 35 additions & 10 deletions lib/archethic/bootstrap.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ defmodule Archethic.Bootstrap do

alias Archethic.Crypto

alias Archethic.P2P.GeoPatch

alias Archethic.Networking

alias Archethic.P2P
Expand Down Expand Up @@ -175,6 +177,7 @@ defmodule Archethic.Bootstrap do
configured_reward_address
) do
Logger.info("Bootstrapping starting")
geo_patch = GeoPatch.from_ip(ip)

cond do
Sync.should_initialize_network?(closest_bootstrapping_nodes) ->
Expand All @@ -187,7 +190,8 @@ defmodule Archethic.Bootstrap do
port,
http_port,
transport,
configured_reward_address
configured_reward_address,
geo_patch
)

Sync.initialize_network(tx)
Expand All @@ -203,7 +207,8 @@ defmodule Archethic.Bootstrap do
http_port,
transport,
closest_bootstrapping_nodes,
configured_reward_address
configured_reward_address,
geo_patch
)

true ->
Expand All @@ -215,15 +220,17 @@ defmodule Archethic.Bootstrap do
)

{:ok, _ip, _p2p_port, _http_port, _transport, last_reward_address, _origin_public_key,
_key_certificate, _mining_public_key} = Node.decode_transaction_content(content)
_key_certificate, _mining_public_key,
_geo_patch} = Node.decode_transaction_content(content)

update_node(
ip,
port,
http_port,
transport,
closest_bootstrapping_nodes,
last_reward_address
last_reward_address,
geo_patch
)
end
end
Expand Down Expand Up @@ -265,7 +272,8 @@ defmodule Archethic.Bootstrap do
http_port,
transport,
closest_bootstrapping_nodes,
configured_reward_address
configured_reward_address,
geo_patch
) do
# In case node had lose it's DB, we ask the network if the node chain already exists
{:ok, length} =
Expand All @@ -286,15 +294,23 @@ defmodule Archethic.Bootstrap do
TransactionChain.fetch_transaction(last_address, closest_bootstrapping_nodes)

{:ok, _ip, _p2p_port, _http_port, _transport, last_reward_address, _origin_public_key,
_key_certificate, _mining_public_key} = Node.decode_transaction_content(content)
_key_certificate, _mining_public_key,
_geo_patch} = Node.decode_transaction_content(content)

last_reward_address
else
configured_reward_address
end

tx =
TransactionHandler.create_node_transaction(ip, port, http_port, transport, reward_address)
TransactionHandler.create_node_transaction(
ip,
port,
http_port,
transport,
reward_address,
geo_patch
)

{:ok, validated_tx} = TransactionHandler.send_transaction(tx, closest_bootstrapping_nodes)

Expand All @@ -307,18 +323,27 @@ defmodule Archethic.Bootstrap do
)
end

defp update_node(_ip, _port, _http_port, _transport, [], _reward_address) do
defp update_node(_ip, _port, _http_port, _transport, [], _reward_address, _geo_patch) do
Logger.warning("Not enough nodes in the network. No node update")
end

defp update_node(ip, port, http_port, transport, closest_bootstrapping_nodes, reward_address) do
defp update_node(
ip,
port,
http_port,
transport,
closest_bootstrapping_nodes,
reward_address,
geo_patch
) do
tx =
TransactionHandler.create_node_transaction(
ip,
port,
http_port,
transport,
reward_address
reward_address,
geo_patch
)

{:ok, validated_tx} = TransactionHandler.send_transaction(tx, closest_bootstrapping_nodes)
Expand Down
15 changes: 12 additions & 3 deletions lib/archethic/bootstrap/transaction_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,18 @@ defmodule Archethic.Bootstrap.TransactionHandler do
p2p_port :: :inet.port_number(),
http_port :: :inet.port_number(),
transport :: P2P.supported_transport(),
reward_address :: Crypto.versioned_hash()
reward_address :: Crypto.versioned_hash(),
geo_patch :: binary()
) ::
Transaction.t()
def create_node_transaction(ip = {_, _, _, _}, port, http_port, transport, reward_address)
def create_node_transaction(
ip = {_, _, _, _},
port,
http_port,
transport,
reward_address,
geo_patch
)
when is_number(port) and port >= 0 and is_binary(reward_address) do
origin_public_key = Crypto.origin_node_public_key()
origin_public_key_certificate = Crypto.get_key_certificate(origin_public_key)
Expand All @@ -102,7 +110,8 @@ defmodule Archethic.Bootstrap.TransactionHandler do
reward_address,
origin_public_key,
origin_public_key_certificate,
mining_public_key
mining_public_key,
geo_patch
)
})
end
Expand Down
15 changes: 13 additions & 2 deletions lib/archethic/mining/pending_transaction_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule Archethic.Mining.PendingTransactionValidation do
alias Archethic.OracleChain

alias Archethic.P2P
alias Archethic.P2P.GeoPatch
alias Archethic.P2P.Message.FirstPublicKey
alias Archethic.P2P.Message.GetFirstPublicKey
alias Archethic.P2P.Node
Expand Down Expand Up @@ -317,7 +318,8 @@ defmodule Archethic.Mining.PendingTransactionValidation do
},
_
) do
with {:ok, ip, port, _http_port, _, _, origin_public_key, key_certificate, mining_public_key} <-
with {:ok, ip, port, _http_port, _, _, origin_public_key, key_certificate, mining_public_key,
geo_patch} <-
Node.decode_transaction_content(content),
{:auth_origin, true} <-
{:auth_origin,
Expand All @@ -338,7 +340,9 @@ defmodule Archethic.Mining.PendingTransactionValidation do
{:mining_public_key, true} <-
{:mining_public_key,
Crypto.valid_public_key?(mining_public_key) and
Crypto.get_public_key_curve(mining_public_key) == :bls} do
Crypto.get_public_key_curve(mining_public_key) == :bls},
{:geo_patch, true} <-
{:geo_patch, valid_geopatch?(ip, geo_patch)} do
:ok
else
:error ->
Expand All @@ -362,6 +366,9 @@ defmodule Archethic.Mining.PendingTransactionValidation do

{:mining_public_key, false} ->
{:error, "Invalid mining public key"}

{:geo_patch, false} ->
{:error, "Invalid geo patch from IP"}
end
end

Expand Down Expand Up @@ -966,6 +973,10 @@ defmodule Archethic.Mining.PendingTransactionValidation do
end
end

defp valid_geopatch?(ip, calculated_geopatch) do
calculated_geopatch == GeoPatch.from_ip(ip)
end

defp get_allowed_node_key_origins do
:archethic
|> Application.get_env(__MODULE__, [])
Expand Down
3 changes: 2 additions & 1 deletion lib/archethic/mining/proof_of_work.ex
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ defmodule Archethic.Mining.ProofOfWork do
}
}) do
{:ok, _ip, _p2p_port, _http_port, _transport, _reward_address, origin_public_key,
_origin_certificate, _mining_public_key} = Node.decode_transaction_content(content)
_origin_certificate, _mining_public_key,
_geo_patch} = Node.decode_transaction_content(content)

[origin_public_key]
end
Expand Down
5 changes: 4 additions & 1 deletion lib/archethic/networking/scheduler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Archethic.Networking.Scheduler do
alias Archethic.Networking.PortForwarding

alias Archethic.P2P
alias(Archethic.P2P.GeoPatch)
alias Archethic.P2P.Listener, as: P2PListener
alias Archethic.P2P.Node

Expand Down Expand Up @@ -103,6 +104,7 @@ defmodule Archethic.Networking.Scheduler do
origin_public_key = Crypto.origin_node_public_key()
mining_public_key = Crypto.mining_node_public_key()
key_certificate = Crypto.get_key_certificate(origin_public_key)
new_geo_patch = GeoPatch.from_ip(ip)

tx =
Transaction.new(:node, %TransactionData{
Expand All @@ -116,7 +118,8 @@ defmodule Archethic.Networking.Scheduler do
reward_address,
origin_public_key,
key_certificate,
mining_public_key
mining_public_key,
new_geo_patch
)
})

Expand Down
8 changes: 5 additions & 3 deletions lib/archethic/p2p/mem_table_loader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ defmodule Archethic.P2P.MemTableLoader do
first_public_key = TransactionChain.get_first_public_key(previous_public_key)

{:ok, ip, port, http_port, transport, reward_address, origin_public_key, _certificate,
mining_public_key} = Node.decode_transaction_content(content)
mining_public_key, geo_patch} = Node.decode_transaction_content(content)

geo_patch = if geo_patch == nil, do: GeoPatch.from_ip(ip), else: geo_patch

if first_node_change?(first_public_key, previous_public_key) do
node = %Node{
Expand All @@ -114,7 +116,7 @@ defmodule Archethic.P2P.MemTableLoader do
http_port: http_port,
first_public_key: first_public_key,
last_public_key: previous_public_key,
geo_patch: GeoPatch.from_ip(ip),
geo_patch: geo_patch,
transport: transport,
last_address: address,
reward_address: reward_address,
Expand All @@ -135,7 +137,7 @@ defmodule Archethic.P2P.MemTableLoader do
port: port,
http_port: http_port,
last_public_key: previous_public_key,
geo_patch: GeoPatch.from_ip(ip),
geo_patch: geo_patch,
transport: transport,
last_address: address,
reward_address: reward_address,
Expand Down
39 changes: 24 additions & 15 deletions lib/archethic/p2p/node.ex
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ defmodule Archethic.P2P.Node do
{:ok, ip_address :: :inet.ip_address(), p2p_port :: :inet.port_number(),
http_port :: :inet.port_number(), P2P.supported_transport(),
reward_address :: binary(), origin_public_key :: Crypto.key(),
key_certificate :: binary(), mining_public_key :: binary() | nil}
key_certificate :: binary(), mining_public_key :: binary() | nil,
geo_patch :: binary() | nil}
| :error
def decode_transaction_content(
<<ip::binary-size(4), port::16, http_port::16, transport::8, rest::binary>>
Expand All @@ -56,18 +57,11 @@ defmodule Archethic.P2P.Node do
{reward_address, rest} <- Utils.deserialize_address(rest),
{origin_public_key, rest} <- Utils.deserialize_public_key(rest),
<<key_certificate_size::16, key_certificate::binary-size(key_certificate_size),
rest::binary>> <- rest do
mining_public_key =
case rest do
"" ->
nil

mining_public_key ->
mining_public_key |> Utils.deserialize_public_key() |> elem(0)
end

rest::binary>> <- rest,
{mining_public_key, rest} <- extract_mining_public_key(rest),
{geo_patch, _rest} <- extract_geo_patch(rest) do
{:ok, {ip0, ip1, ip2, ip3}, port, http_port, deserialize_transport(transport),
reward_address, origin_public_key, key_certificate, mining_public_key}
reward_address, origin_public_key, key_certificate, mining_public_key, geo_patch}
else
_ ->
:error
Expand All @@ -76,6 +70,19 @@ defmodule Archethic.P2P.Node do

def decode_transaction_content(<<>>), do: :error

@spec extract_mining_public_key(binary()) :: {Crypto.key() | nil, binary()}
defp extract_mining_public_key(<<>>), do: {nil, <<>>}

defp extract_mining_public_key(rest) do
{mining_public_key, remaining} = Utils.deserialize_public_key(rest)
{mining_public_key, remaining}
end

@spec extract_geo_patch(binary()) :: {binary() | nil, binary()}
defp extract_geo_patch(<<geo_patch::binary-size(3), rest::binary>>), do: {geo_patch, rest}

defp extract_geo_patch(rest), do: {nil, rest}

@doc """
Encode node's transaction content
"""
Expand All @@ -87,7 +94,8 @@ defmodule Archethic.P2P.Node do
reward_address :: binary(),
origin_public_key :: Crypto.key(),
origin_key_certificate :: binary(),
mining_public_key :: Crypto.key()
mining_public_key :: Crypto.key(),
geo_patch :: binary()
) :: binary()
def encode_transaction_content(

Check warning on line 100 in lib/archethic/p2p/node.ex

View workflow job for this annotation

GitHub Actions / Build and test

Function takes too many parameters (arity is 9, max is 8).
{ip1, ip2, ip3, ip4},
Expand All @@ -97,11 +105,12 @@ defmodule Archethic.P2P.Node do
reward_address,
origin_public_key,
key_certificate,
mining_public_key
mining_public_key,
geo_patch
) do
<<ip1, ip2, ip3, ip4, port::16, http_port::16, serialize_transport(transport)::8,
reward_address::binary, origin_public_key::binary, byte_size(key_certificate)::16,
key_certificate::binary, mining_public_key::binary>>
key_certificate::binary, mining_public_key::binary, geo_patch::binary-size(3)>>
end

@type t() :: %__MODULE__{
Expand Down
2 changes: 1 addition & 1 deletion lib/archethic/shared_secrets/mem_tables_loader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ defmodule Archethic.SharedSecrets.MemTablesLoader do
}
}) do
{:ok, _ip, _p2p_port, _http_port, _transport, _reward_address, origin_public_key, _cert,
_mining_public_key} = Node.decode_transaction_content(content)
_mining_public_key, _geo_patch} = Node.decode_transaction_content(content)

<<_::8, origin_id::8, _::binary>> = origin_public_key

Expand Down
8 changes: 6 additions & 2 deletions lib/archethic_web/explorer/live/settings_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ defmodule ArchethicWeb.Explorer.SettingsLive do
defp send_new_transaction(next_reward_address) do
%Node{
ip: ip,
geo_patch: geo_patch,
port: port,
http_port: http_port,
transport: transport,
Expand Down Expand Up @@ -157,7 +158,8 @@ defmodule ArchethicWeb.Explorer.SettingsLive do
next_reward_address,
Crypto.origin_node_public_key(),
Crypto.get_key_certificate(Crypto.origin_node_public_key()),
Crypto.mining_node_public_key()
Crypto.mining_node_public_key(),
geo_patch
)
})

Expand All @@ -169,6 +171,7 @@ defmodule ArchethicWeb.Explorer.SettingsLive do
defp send_noop_transaction() do
%Node{
ip: ip,
geo_patch: geo_patch,
port: port,
http_port: http_port,
transport: transport,
Expand All @@ -192,7 +195,8 @@ defmodule ArchethicWeb.Explorer.SettingsLive do
reward_address,
Crypto.origin_node_public_key(),
Crypto.get_key_certificate(Crypto.origin_node_public_key()),
Crypto.mining_node_public_key()
Crypto.mining_node_public_key(),
geo_patch
)
})

Expand Down
Loading

0 comments on commit 98184eb

Please sign in to comment.