Skip to content

Commit

Permalink
Add timestamp in node validation election
Browse files Browse the repository at this point in the history
  • Loading branch information
wassimans committed Nov 5, 2024
1 parent 507c4be commit 8b6d24d
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 125 deletions.
3 changes: 2 additions & 1 deletion lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ defmodule Archethic do
welcome_node_key = Keyword.get(opts, :welcome_node_key, Crypto.first_node_public_key())
contract_context = Keyword.get(opts, :contract_context, nil)
forward? = Keyword.get(opts, :forward?, false)
ref_timestamp = DateTime.utc_now()

cond do
P2P.authorized_and_available_node?() and shared_secret_synced?() ->
validation_nodes = Mining.get_validation_nodes(tx)
validation_nodes = Mining.get_validation_nodes(tx, ref_timestamp)

responses =
%{already_locked?: already_locked?} =
Expand Down
5 changes: 4 additions & 1 deletion lib/archethic/election.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ defmodule Archethic.Election do
"""
@spec validation_nodes_election_seed_sorting(Transaction.t(), DateTime.t()) :: binary()
def validation_nodes_election_seed_sorting(tx = %Transaction{}, timestamp = %DateTime{}) do
tx_hash =
serialized_tx =
tx
|> Transaction.to_pending()
|> Transaction.serialize()

tx_hash =
<<serialized_tx::bitstring, DateTime.to_unix(timestamp, :millisecond)::64>>
|> Crypto.hash()

Crypto.sign_with_daily_nonce_key(tx_hash, timestamp)
Expand Down
14 changes: 9 additions & 5 deletions lib/archethic/mining.ex
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,12 @@ defmodule Archethic.Mining do
@doc """
Elect validation nodes for a transaction
"""
def get_validation_nodes(tx = %Transaction{address: tx_address, validation_stamp: nil}) do
def get_validation_nodes(
tx = %Transaction{address: tx_address, validation_stamp: nil},
ref_timestamp
) do
current_date = DateTime.utc_now()
sorting_seed = Election.validation_nodes_election_seed_sorting(tx, current_date)
sorting_seed = Election.validation_nodes_election_seed_sorting(tx, ref_timestamp)

node_list = P2P.authorized_and_available_nodes(current_date)

Expand All @@ -100,10 +103,11 @@ defmodule Archethic.Mining do
@doc """
Determines if the election of validation nodes performed by the welcome node is valid
"""
@spec valid_election?(Transaction.t(), list(Crypto.key())) :: boolean()
def valid_election?(tx, validation_node_public_keys)
@spec valid_election?(Transaction.t(), list(Crypto.key()), ref_timestamp :: DateTime.t()) ::
boolean()
def valid_election?(tx, validation_node_public_keys, ref_timestamp)
when is_list(validation_node_public_keys) do
validation_nodes = get_validation_nodes(tx)
validation_nodes = get_validation_nodes(tx, ref_timestamp)
validation_node_public_keys == Enum.map(validation_nodes, & &1.last_public_key)
end

Expand Down
4 changes: 2 additions & 2 deletions lib/archethic/mining/distributed_workflow.ex
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ defmodule Archethic.Mining.DistributedWorkflow do
:internal,
{:start_mining, tx, welcome_node, validation_nodes, contract_context},
:idle,
data = %{node_public_key: node_public_key}
data = %{ref_timestamp: ref_timestamp, node_public_key: node_public_key}
) do
validation_time = DateTime.utc_now() |> DateTime.truncate(:millisecond)
validation_time = ref_timestamp |> DateTime.truncate(:millisecond)

authorized_nodes = P2P.authorized_and_available_nodes(validation_time)

Expand Down
6 changes: 3 additions & 3 deletions lib/archethic/p2p/message/start_mining.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ defmodule Archethic.P2P.Message.StartMining do
) do
with :ok <- check_ref_timestamp(ref_timestamp),
:ok <- check_synchronization(network_chains_view_hash, p2p_view_hash),
:ok <- check_valid_election(tx, validation_nodes),
:ok <- check_valid_election(tx, validation_nodes, ref_timestamp),
:ok <- check_current_node_is_elected(validation_nodes),
:ok <- check_not_already_mining(tx.address),
:ok <- Mining.request_chain_lock(tx) do
Expand Down Expand Up @@ -212,8 +212,8 @@ defmodule Archethic.P2P.Message.StartMining do
end
end

defp check_valid_election(tx, validation_nodes) do
if Mining.valid_election?(tx, validation_nodes) do
defp check_valid_election(tx, validation_nodes, ref_timestamp) do
if Mining.valid_election?(tx, validation_nodes, ref_timestamp) do
:ok
else
{:error, :invalid_validation_nodes_election}
Expand Down
Loading

0 comments on commit 8b6d24d

Please sign in to comment.