Skip to content

Commit

Permalink
Add new index for last chain address stored
Browse files Browse the repository at this point in the history
  • Loading branch information
Neylix committed Jun 21, 2023
1 parent 1a5cf71 commit 01359a1
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 14 deletions.
2 changes: 2 additions & 0 deletions lib/archethic/db.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ defmodule Archethic.DB do
@callback list_chain_public_keys(binary(), DateTime.t()) ::
Enumerable.t() | list({binary(), DateTime.t()})

@callback get_last_chain_address_stored(genesis_address :: Crypto.prepended_hash()) ::
Crypto.prepended_hash() | nil
@callback get_last_chain_address(binary()) :: {binary(), DateTime.t()}
@callback get_last_chain_address(binary(), DateTime.t()) :: {binary(), DateTime.t()}
@callback get_last_chain_public_key(binary()) :: Crypto.key()
Expand Down
9 changes: 9 additions & 0 deletions lib/archethic/db/embedded_impl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,15 @@ defmodule Archethic.DB.EmbeddedImpl do
ChainIndex.count_transactions_by_type(type)
end

@doc """
Return the last address stored for a chain
"""
@spec get_last_chain_address_stored(genesis_address :: Crypto.prepended_hash()) ::
Crypto.prepended_hash() | nil
def get_last_chain_address_stored(genesis_address) when is_binary(genesis_address) do
ChainIndex.get_last_chain_address_stored(genesis_address, db_path())
end

@doc """
Return the last address from the given transaction's address until the given date along with its timestamp
"""
Expand Down
34 changes: 34 additions & 0 deletions lib/archethic/db/embedded_impl/chain_index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,33 @@ defmodule Archethic.DB.EmbeddedImpl.ChainIndex do
:ok
end

@doc """
Set the last stored address
"""
@spec set_last_chain_address_stored(
genesis_address :: Crypto.prepended_hash(),
tx_address :: Crypto.prepended_hash(),
db_path :: binary()
) :: :ok
def set_last_chain_address_stored(genesis_address, tx_address, db_path),
do: last_chain_address_stored_path(db_path, genesis_address) |> File.write!(tx_address)

@doc """
Return the last address stored for a chain
"""
@spec get_last_chain_address_stored(
genesis_address :: Crypto.prepended_hash(),
db_path :: binary()
) :: Crypto.prepended_hash() | nil
def get_last_chain_address_stored(genesis_address, db_path) do
filename = last_chain_address_stored_path(db_path, genesis_address)

case File.read(filename) do
{:ok, address} -> address
_ -> nil
end
end

@doc """
Reference a new transaction address for the genesis address at the transaction time
"""
Expand Down Expand Up @@ -713,6 +740,13 @@ defmodule Archethic.DB.EmbeddedImpl.ChainIndex do
])
end

defp last_chain_address_stored_path(db_path, genesis_address) do
Path.join([
ChainWriter.base_chain_path(db_path),
"#{Base.encode16(genesis_address)}-last-stored-address"
])
end

defp type_path(db_path, type) do
Path.join([ChainWriter.base_chain_path(db_path), Atom.to_string(type)])
end
Expand Down
1 change: 1 addition & 0 deletions lib/archethic/db/embedded_impl/chain_writer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ defmodule Archethic.DB.EmbeddedImpl.ChainWriter do

ChainIndex.add_tx(tx_address, genesis_address, encoded_size, db_path)
ChainIndex.add_tx_type(tx_type, tx_address, db_path)
ChainIndex.set_last_chain_address_stored(genesis_address, tx_address, db_path)
ChainIndex.set_last_chain_address(genesis_address, tx_address, timestamp, db_path)
ChainIndex.set_public_key(genesis_address, previous_public_key, timestamp, db_path)

Expand Down
10 changes: 3 additions & 7 deletions lib/archethic/transaction_chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1027,13 +1027,9 @@ defmodule Archethic.TransactionChain do
@doc """
Retrieve the last transaction address for a chain stored locally
"""
@spec get_last_stored_address(genesis_address :: binary()) :: binary() | nil
def get_last_stored_address(genesis_address) do
list_chain_addresses(genesis_address)
|> Enum.reduce_while(nil, fn {address, _}, acc ->
if transaction_exists?(address), do: {:cont, address}, else: {:halt, acc}
end)
end
@spec get_last_stored_address(genesis_address :: Crypto.prepended_hash()) ::
Crypto.prepended_hash() | nil
defdelegate get_last_stored_address(genesis_address), to: DB, as: :get_last_chain_address_stored

@doc """
Retrieve the genesis address for a chain from P2P Quorom
Expand Down
15 changes: 15 additions & 0 deletions test/archethic/db/embedded_impl/chain_index_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ defmodule Archethic.DB.EmbeddedImpl.ChainIndexTest do
alias Archethic.DB.EmbeddedImpl.ChainWriter
alias ArchethicCache.LRU

import ArchethicCase

setup do
db_path = Application.app_dir(:archethic, "data_test")
ChainWriter.setup_folders!(db_path)
Expand Down Expand Up @@ -99,4 +101,17 @@ defmodule Archethic.DB.EmbeddedImpl.ChainIndexTest do
assert {^tx_address_2, _} = ChainIndex.get_last_chain_address(genesis_address, db_path)
end
end

describe "set_last_chain_address_stored" do
test "should write a new index containing the address", %{db_path: db_path} do
genesis_address = random_address()
last_address = random_address()

assert nil == ChainIndex.get_last_chain_address_stored(genesis_address, db_path)

ChainIndex.set_last_chain_address_stored(genesis_address, last_address, db_path)

assert last_address == ChainIndex.get_last_chain_address_stored(genesis_address, db_path)
end
end
end
8 changes: 1 addition & 7 deletions test/archethic/replication/transaction_context_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,7 @@ defmodule Archethic.Replication.TransactionContextTest do
addr2 = Crypto.derive_address(pub2)

MockDB
|> stub(:list_chain_addresses, fn _ ->
[{addr1, DateTime.utc_now()}, {addr2, DateTime.utc_now()}]
end)
|> stub(:transaction_exists?, fn
^addr1, _ -> true
_, _ -> false
end)
|> stub(:get_last_chain_address_stored, fn _ -> addr1 end)

MockClient
|> stub(:send_message, fn
Expand Down
1 change: 1 addition & 0 deletions test/support/template.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ defmodule ArchethicCase do
|> stub(:stop_inputs_writer, fn _ -> :ok end)
|> stub(:append_input, fn _, _ -> :ok end)
|> stub(:get_inputs, fn _, _ -> [] end)
|> stub(:get_last_chain_address_stored, fn addr -> addr end)

{:ok, shared_secrets_counter} = Agent.start_link(fn -> 0 end)
{:ok, network_pool_counter} = Agent.start_link(fn -> 0 end)
Expand Down

0 comments on commit 01359a1

Please sign in to comment.