Skip to content

Commit

Permalink
welcome_node_should_forward_tx_if_not_synced#872
Browse files Browse the repository at this point in the history
 - Check for whether a node is synced for every tx
 - If not schedule a request for resync

 DrawBacks
 - NSS chain has to be checked for each tx

 Solution
 - Instead of checking for each tx , we can check in time duration
   where such scenario can happen
 - That is when, we expect a new node renewal tx
 -  we check for whether nss chain is synced b/w 23:50 to say 1:00
 -  how to achieve this?
 - if the time diff of current time and last_scheduling date is b/w
 - 10% of nss cycle for tx creation, which in prod is 24, so 2.4hrs
 - or can be 1.2 hrs with 5 percent.

 @samuelmanzanera
 @Neylix
 What do you think guys?
  • Loading branch information
apoorv-2204 committed Feb 7, 2023
1 parent 1c03c75 commit 4907215
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 29 deletions.
35 changes: 27 additions & 8 deletions lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ defmodule Archethic do
alias __MODULE__.TransactionChain.TransactionInput
alias __MODULE__.TransactionChain.TransactionSummary

alias Archethic.SelfRepair.ResyncWorker

require Logger

@doc """
Expand Down Expand Up @@ -60,17 +62,34 @@ defmodule Archethic do
tx = %Transaction{},
welcome_node_key \\ Crypto.first_node_public_key()
) do
if P2P.authorized_and_available_node?() do
do_send_transaction(tx, welcome_node_key)
else
P2P.authorized_and_available_nodes()
|> Enum.filter(&Node.locally_available?/1)
|> P2P.nearest_nodes()
|> forward_transaction(tx)
handle_new_tx(tx, welcome_node_key)
end

def handle_new_tx(tx, welcome_node_key) do
synced? = P2P.is_synced_node?()
allowed? = P2P.authorized_and_available_node?()

cond do
!allowed? ->
forward_transaction(tx)

allowed? && synced? ->
do_send_transaction(tx, welcome_node_key)

!synced? ->
ResyncWorker.sync_again()
forward_transaction(tx)
end
end

defp forward_transaction([node | rest], tx) do
def forward_transaction(tx) do
P2P.authorized_and_available_nodes()
|> Enum.filter(&Node.locally_available?/1)
|> P2P.nearest_nodes()
|> do_forward_transaction(tx)
end

defp do_forward_transaction([node | rest], tx) do
case P2P.send_message(node, %NewTransaction{transaction: tx}) do
{:ok, %Ok{}} ->
:ok
Expand Down
29 changes: 15 additions & 14 deletions lib/archethic/p2p.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,11 @@ defmodule Archethic.P2P do
@moduledoc """
Handle P2P node discovery and messaging
"""
alias Archethic.Crypto
alias Archethic.{Crypto, SharedSecrets, TaskSupervisor, TransactionChain}

alias __MODULE__.BootstrappingSeeds
alias __MODULE__.Client
alias __MODULE__.GeoPatch
alias __MODULE__.MemTable
alias __MODULE__.MemTableLoader
alias __MODULE__.Message
alias __MODULE__.Node
alias Archethic.{TransactionChain.Transaction, Utils}

alias Archethic.TaskSupervisor

alias Archethic.TransactionChain
alias Archethic.TransactionChain.Transaction

alias Archethic.Utils
alias __MODULE__.{BootstrappingSeeds, Client, GeoPatch, MemTable, MemTableLoader, Message, Node}

require Logger

Expand Down Expand Up @@ -761,4 +750,16 @@ defmodule Archethic.P2P do
conflict_resolver.(distinct_elems)
end
end

@doc """
is NSS chain in sync
"""
@spec is_synced_node?() :: boolean()
def is_synced_node?(), do: SharedSecrets.is_synchronized?(:node_shared_secrets)

def exclusive_nodes() do
__MODULE__.authorized_and_available_nodes()
|> Enum.filter(&__MODULE__.Node.locally_available?/1)
|> Enum.reject(&(&1.first_public_key == Crypto.first_node_public_key()))
end
end
4 changes: 2 additions & 2 deletions lib/archethic/self_repair/supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ defmodule Archethic.SelfRepair.Supervisor do

use Supervisor

alias Archethic.SelfRepair.Scheduler
alias Archethic.Utils
alias Archethic.{SelfRepair.Scheduler, Utils, SelfRepair.ResyncWorker}

def start_link(arg) do
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
end

def init(_arg) do
children = [
{ResyncWorker, []},
{Scheduler, Application.get_env(:archethic, Scheduler)},
{DynamicSupervisor, strategy: :one_for_one, name: Archethic.SelfRepair.NotifierSupervisor},
{Registry,
Expand Down
30 changes: 30 additions & 0 deletions lib/archethic/shared_secrets.ex
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,34 @@ defmodule Archethic.SharedSecrets do
def origin_family_from_public_key(<<_curve_id::8, origin_id::8, _public_key::binary>>) do
get_origin_family_from_origin_id(origin_id)
end

@doc """
Determines whether the chain is in Sync.
when in Sync(15thJan 23:58)
last_scheduling_date 15thJan 23:50
validation_timestamp 15thJan 23:55
validation_timestamp > last_scheduling_date returns true
when not in Sync(16thJan 23:58)
last_scheduling_date 16thJan 23:50
validation_timestamp 15thJan 23:55
validation_timestamp > last_scheduling_date
returns false
"""
@spec is_synchronized?(:node_shared_secrets) :: boolean
def is_synchronized?(:node_shared_secrets) do
last_scheduling_date =
DateTime.utc_now()
|> __MODULE__.get_last_scheduling_date()

%{__struct__: _, validation_stamp: %{__struct__: _, timestamp: validation_timestamp}} =
__MODULE__.genesis_address(:node_shared_secrets)
|> TransactionChain.get_last_transaction(validation_stamp: [:timestamp])
|> elem(1)

validation_timestamp > last_scheduling_date
end
end
2 changes: 1 addition & 1 deletion src/c/nat/miniupnp
9 changes: 5 additions & 4 deletions test/archethic/bootstrap_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ defmodule Archethic.BootstrapTest do
SharedSecrets,
SharedSecrets.NodeRenewalScheduler,
TransactionChain,
TransactionFactory
TransactionFactory,
SelfRepair.ResyncWorker
}

alias Archethic.P2P.Message.{
Expand Down Expand Up @@ -500,7 +501,7 @@ defmodule Archethic.BootstrapTest do
:persistent_term.put(:node_shared_secrets_gen_addr, nil)

assert :ok =
Bootstrap.do_resync_network_chain(
ResyncWorker.resync(
:node_shared_secrets,
_nodes = P2P.authorized_and_available_nodes()
)
Expand Down Expand Up @@ -528,7 +529,7 @@ defmodule Archethic.BootstrapTest do
end)

assert :ok =
Bootstrap.do_resync_network_chain(
ResyncWorker.resync(
:node_shared_secrets,
_nodes = P2P.authorized_and_available_nodes()
)
Expand Down Expand Up @@ -599,7 +600,7 @@ defmodule Archethic.BootstrapTest do
end)

assert :ok =
Bootstrap.do_resync_network_chain(
ResyncWorker.resync(
:node_shared_secrets,
_nodes = P2P.authorized_and_available_nodes()
)
Expand Down

0 comments on commit 4907215

Please sign in to comment.