From 15c7679a6b1bc166999269c558b1716f66f0c8ac Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 8 Apr 2022 15:55:04 +0200 Subject: [PATCH] Fix the shared secret keystore loading Because of the new DB design, the order of transaction is not desc but asc. So the loader had to be changed, to load the latest transaction --- .../keystore/shared_secrets/software_impl.ex | 61 +++++++++---------- lib/archethic/db.ex | 3 + lib/archethic/db/embedded_impl.ex | 8 +++ lib/archethic/transaction_chain.ex | 6 ++ .../shared_secrets/software_impl_test.exs | 27 ++++---- test/support/template.ex | 1 + 6 files changed, 63 insertions(+), 43 deletions(-) diff --git a/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex b/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex index 57e84f625..c39f43e1e 100644 --- a/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex +++ b/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex @@ -34,17 +34,8 @@ defmodule ArchEthic.Crypto.SharedSecretsKeystore.SoftwareImpl do load_storage_nonce() - node_shared_secrets_chain = - TransactionChain.list_transactions_by_type( - :node_shared_secrets, - [ - :address, - data: [:ownerships], - validation_stamp: [:timestamp] - ] - ) - - nb_node_shared_secrets_keys = Enum.count(node_shared_secrets_chain) + nb_node_shared_secrets_keys = + TransactionChain.count_transactions_by_type(:node_shared_secrets) Logger.info("Node shared secrets keys positioned at #{nb_node_shared_secrets_keys}") @@ -54,7 +45,11 @@ defmodule ArchEthic.Crypto.SharedSecretsKeystore.SoftwareImpl do :ets.insert(@keystore_table, {:shared_secrets_index, nb_node_shared_secrets_keys}) :ets.insert(@keystore_table, {:network_pool_index, nb_network_pool_keys}) - load_node_shared_secrets_chain(node_shared_secrets_chain) + :node_shared_secrets + |> TransactionChain.list_addresses_by_type() + |> Enum.at(-1) + |> load_node_shared_secrets_tx() + {:ok, %{}} end @@ -68,29 +63,33 @@ defmodule ArchEthic.Crypto.SharedSecretsKeystore.SoftwareImpl do end end - defp load_node_shared_secrets_chain(chain) do - case Enum.at(chain, 0) do - nil -> - :ok + defp load_node_shared_secrets_tx(nil), do: :ok + + defp load_node_shared_secrets_tx(address) do + {:ok, + %Transaction{ + data: %TransactionData{ + ownerships: [ownership = %Ownership{secret: secret}] + }, + validation_stamp: %ValidationStamp{timestamp: timestamp} + }} = + TransactionChain.get_transaction(address, [ + :address, + data: [:ownerships], + validation_stamp: [:timestamp] + ]) - %Transaction{ - address: address, - data: %TransactionData{ownerships: [ownership = %Ownership{secret: secret}]}, - validation_stamp: %ValidationStamp{timestamp: timestamp} - } -> - if Ownership.authorized_public_key?(ownership, Crypto.last_node_public_key()) do - encrypted_secret_key = - Ownership.get_encrypted_key(ownership, Crypto.last_node_public_key()) + if Ownership.authorized_public_key?(ownership, Crypto.last_node_public_key()) do + encrypted_secret_key = Ownership.get_encrypted_key(ownership, Crypto.last_node_public_key()) - daily_nonce_date = SharedSecrets.next_application_date(timestamp) + daily_nonce_date = SharedSecrets.next_application_date(timestamp) - :ok = do_unwrap_secrets(secret, encrypted_secret_key, daily_nonce_date) + :ok = do_unwrap_secrets(secret, encrypted_secret_key, daily_nonce_date) - Logger.info("Node shared secrets loaded", - transaction_address: Base.encode16(address), - transaction_type: :node_shared_secrets - ) - end + Logger.info("Node shared secrets loaded", + transaction_address: Base.encode16(address), + transaction_type: :node_shared_secrets + ) end end diff --git a/lib/archethic/db.ex b/lib/archethic/db.ex index 5852e4f27..401ad879f 100644 --- a/lib/archethic/db.ex +++ b/lib/archethic/db.ex @@ -26,6 +26,9 @@ defmodule ArchEthic.DB do Enumerable.t() @callback count_transactions_by_type(type :: Transaction.transaction_type()) :: non_neg_integer() + + @callback list_addresses_by_type(Transaction.transaction_type()) :: + Enumerable.t() | list(binary()) @callback get_last_chain_address(binary()) :: binary() @callback get_last_chain_address(binary(), DateTime.t()) :: binary() @callback get_first_chain_address(binary()) :: binary() diff --git a/lib/archethic/db/embedded_impl.ex b/lib/archethic/db/embedded_impl.ex index d6b4e4f19..7cd3c53f9 100644 --- a/lib/archethic/db/embedded_impl.ex +++ b/lib/archethic/db/embedded_impl.ex @@ -130,6 +130,14 @@ defmodule ArchEthic.DB.EmbeddedImpl do end) end + @doc """ + Stream all the addresses for a transaction type + """ + @spec list_addresses_by_type(Transaction.transaction_type()) :: Enumerable.t() | list(binary()) + def list_addresses_by_type(type) when is_atom(type) do + ChainIndex.get_addresses_by_type(type, db_path()) + end + @doc """ Count the number of transactions for a given type """ diff --git a/lib/archethic/transaction_chain.ex b/lib/archethic/transaction_chain.ex index 67aa1dd67..60cd166a8 100644 --- a/lib/archethic/transaction_chain.ex +++ b/lib/archethic/transaction_chain.ex @@ -43,6 +43,12 @@ defmodule ArchEthic.TransactionChain do @spec count_transactions_by_type(type :: Transaction.transaction_type()) :: non_neg_integer() defdelegate count_transactions_by_type(type), to: DB + @doc """ + Stream all the addresses for a transaction type + """ + @spec list_addresses_by_type(Transaction.transaction_type()) :: Enumerable.t() | list(binary()) + defdelegate list_addresses_by_type(type), to: DB + @doc """ Get the last transaction address from a transaction chain """ diff --git a/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs b/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs index 20bbe5749..869a04e56 100644 --- a/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs +++ b/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs @@ -26,20 +26,23 @@ defmodule ArchEthic.Crypto.SharedSecrets.SoftwareImplTest do timestamp = ~U[2021-10-10 00:00:00Z] MockDB - |> expect(:count_transactions_by_type, fn + |> stub(:count_transactions_by_type, fn :node_rewards -> 1 + :node_shared_secrets -> 1 end) - |> expect(:list_transactions_by_type, fn :node_shared_secrets, _ -> - [ - %Transaction{ - data: %TransactionData{ - ownerships: [Ownership.new(secrets, aes_key, [Crypto.last_node_public_key()])] - }, - validation_stamp: %ValidationStamp{ - timestamp: timestamp - } - } - ] + |> expect(:list_addresses_by_type, fn :node_shared_secrets -> + [:crypto.strong_rand_bytes(32)] + end) + |> expect(:get_transaction, fn _, _ -> + {:ok, + %Transaction{ + data: %TransactionData{ + ownerships: [Ownership.new(secrets, aes_key, [Crypto.last_node_public_key()])] + }, + validation_stamp: %ValidationStamp{ + timestamp: timestamp + } + }} end) {:ok, _pid} = Keystore.start_link() diff --git a/test/support/template.ex b/test/support/template.ex index 92220df63..2ce543eac 100644 --- a/test/support/template.ex +++ b/test/support/template.ex @@ -47,6 +47,7 @@ defmodule ArchEthicCase do |> stub(:chain_size, fn _ -> 0 end) |> stub(:list_transactions_by_type, fn _, _ -> [] end) |> stub(:count_transactions_by_type, fn _ -> 0 end) + |> stub(:list_addresses_by_type, fn _ -> [] end) |> stub(:list_transactions, fn _ -> [] end) |> stub(:transaction_exists?, fn _ -> false end) |> stub(:register_p2p_summary, fn _, _, _, _ -> :ok end)