Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/aecore/lib/aecore.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Aecore do
supervisor(Aecore.Chain.Worker.Supervisor, []),
supervisor(Aecore.Miner.Worker.Supervisor, []),
supervisor(Aecore.Txs.Pool.Worker.Supervisor, []),
supervisor(Aecore.Peers.Worker, [])
supervisor(Aecore.Peers.Worker.Supervisor, [])
]

Supervisor.start_link(children, strategy: :one_for_one)
Expand Down
26 changes: 26 additions & 0 deletions apps/aecore/lib/aecore/peers/scheduler.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule Aecore.Peers.Scheduler do
use GenServer

alias Aecore.Peers.Worker, as: Peers

@check_time 60_000

def start_link do
GenServer.start_link(__MODULE__, %{})
end

def init(state) do
schedule_work()
{:ok, state}
end

def handle_info(:work, state) do
Peers.check_peers()
schedule_work()
{:noreply, state}
end

defp schedule_work() do
Process.send_after(self(), :work, @check_time)
end
end
55 changes: 33 additions & 22 deletions apps/aecore/lib/aecore/peers/worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defmodule Aecore.Peers.Worker do
alias Aecore.Utils.Blockchain.BlockValidation

def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
end

def init(initial_peers) do
Expand All @@ -32,7 +32,7 @@ defmodule Aecore.Peers.Worker do
GenServer.call(__MODULE__, :check_peers)
end

@spec all_peers() :: list()
@spec all_peers() :: map()
def all_peers() do
GenServer.call(__MODULE__, :all_peers)
end
Expand All @@ -45,36 +45,47 @@ defmodule Aecore.Peers.Worker do
end

def handle_call({:add_peer,uri}, _from, peers) do
if(!Enum.member?(peers,uri)) do
case(Client.get_info(uri)) do
{:ok, info} ->
if(Map.get(info,:genesis_block_hash) == genesis_block_header_hash()) do
{:reply, :ok, [uri | peers]}
else
{:reply, {:error, "Genesis header hash not valid"}, peers}
end
:error ->
{:reply, :error, peers}
end
else
{:reply, {:error, "Peer already in list"}, peers}
case(Client.get_info(uri)) do
{:ok, info} ->
if(info.genesis_block_hash == genesis_block_header_hash()) do
updated_peers = Map.put(peers, uri, info.current_block_hash)
{:reply, :ok, updated_peers}
else
{:reply, {:error, "Genesis header hash not valid"}, peers}
end
:error ->
{:reply, :error, peers}
end
end

def handle_call({:remove_peer, uri}, _from, peers) do
if(Enum.member?(peers,uri)) do
{:reply, :ok, List.delete(peers, uri)}
if(Map.has_key?(peers, uri)) do
{:reply, :ok, Map.delete(peers, uri)}
else
{:reply, {:error, "Peer not found"}, peers}
end
end

@doc """
Filters the peers map by checking if the response status from a GET /info
request is :ok and if the genesis block hash is the same as the one
in the current node. After that the current block hash for every peer
is updated if the one in the latest GET /info request is different.
"""
def handle_call(:check_peers, _from, peers) do
updated_peers = Enum.filter(peers, fn(peer) ->
{status, info} = Client.get_info(peer)
:ok == status &&
Map.get(info, :genesis_block_hash) == genesis_block_header_hash()
end)
filtered_peers = :maps.filter(fn(peer, _) ->
{status, info} = Client.get_info(peer)
:ok == status && info.genesis_block_hash == genesis_block_header_hash()
end, peers)
updated_peers =
for {peer, current_block_hash} <- filtered_peers, into: %{} do
{_, info} = Client.get_info(peer)
if(info.current_block_hash != current_block_hash) do
{peer, info.current_block_hash}
else
{peer, current_block_hash}
end
end
{:reply, :ok, updated_peers}
end

Expand Down
5 changes: 3 additions & 2 deletions apps/aecore/lib/aecore/peers/worker/supervisor.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Aecore.Peers.Supervisor do
defmodule Aecore.Peers.Worker.Supervisor do
use Supervisor

def start_link() do
Expand All @@ -7,7 +7,8 @@ defmodule Aecore.Peers.Supervisor do

def init(:ok) do
children = [
worker(Aecore.Peers.Worker, [])
worker(Aecore.Peers.Worker, []),
worker(Aecore.Peers.Scheduler, [])
]

supervise(children, strategy: :one_for_one)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ defmodule Aecore.Utils.Blockchain.BlockValidation do
alias Aecore.Structures.Header
alias Aecore.Structures.SignedTx
alias Aecore.Chain.ChainState
alias Aecore.Chain.Worker, as: Chain

@spec validate_block!(Block.block(), Block.block(), map()) :: {:error, term()} | :ok
def validate_block!(new_block, previous_block, chain_state) do
Expand Down
2 changes: 1 addition & 1 deletion apps/aecore/test/aecore_peers_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule AecorePeersTest do

test "add peer, get all peers, check peers and remove the peer" do
assert :ok = Peers.add_peer("localhost:4000")
assert {:error, "Peer already in list"} = Peers.add_peer("localhost:4000")
Peers.add_peer("localhost:4000")
assert Enum.count(Peers.all_peers) == 1
assert :ok = Peers.check_peers
assert :ok = Peers.remove_peer("localhost:4000")
Expand Down