Skip to content

Commit ae953e4

Browse files
committed
Merge branch 'master' into GH-88
# Conflicts: # apps/aecore/lib/aecore/chain/worker.ex
2 parents e183f3e + bc4dbc7 commit ae953e4

File tree

11 files changed

+89
-51
lines changed

11 files changed

+89
-51
lines changed

apps/aecore/lib/aecore/chain/worker.ex

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ defmodule Aecore.Chain.Worker do
99
alias Aecore.Chain.ChainState
1010
alias Aecore.Txs.Pool.Worker, as: Pool
1111
alias Aecore.Utils.Blockchain.BlockValidation
12+
alias Aecore.Peers.Worker, as: Peers
1213

1314
use GenServer
1415

@@ -127,15 +128,14 @@ defmodule Aecore.Chain.Worker do
127128

128129
total_tokens = ChainState.calculate_total_tokens(new_chain_state)
129130

130-
Logger.info(
131-
fn ->
132-
"Added block ##{block.header.height} with hash #{
133-
block.header
134-
|> BlockValidation.block_header_hash()
135-
|> Base.encode16()
136-
}, total tokens: #{total_tokens}"
137-
end
138-
)
131+
Logger.info(fn ->
132+
"Added block ##{block.header.height} with hash #{block.header
133+
|> BlockValidation.block_header_hash()
134+
|> Base.encode16()}, total tokens: #{total_tokens}"
135+
end)
136+
137+
## Block was validated, now we can send it to other peers
138+
Peers.broadcast_to_all({:new_block, block})
139139

140140
{:reply, :ok, {updated_block_map, updated_latest_block_chainstate}}
141141
catch

apps/aecore/lib/aecore/peers/worker.ex

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ defmodule Aecore.Peers.Worker do
88
alias Aehttpclient.Client
99
alias Aecore.Structures.Block
1010
alias Aecore.Utils.Blockchain.BlockValidation
11+
alias Aehttpclient.Client, as: HttpClient
1112
alias Aecore.Utils.Serialization
1213

14+
1315
require Logger
1416

1517
def start_link do
1618
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
1719
end
1820

19-
def init(initial_peers) do
20-
{:ok, initial_peers}
21-
end
21+
## Client side
2222

2323
@spec add_peer(term) :: :ok | {:error, term()} | :error
2424
def add_peer(uri) do
@@ -40,18 +40,29 @@ defmodule Aecore.Peers.Worker do
4040
GenServer.call(__MODULE__, :all_peers)
4141
end
4242

43-
@spec broadcast_tx(tx :: map()) :: term()
44-
def broadcast_tx(tx) do
45-
GenServer.cast(__MODULE__, {:broadcast_tx, tx})
46-
end
47-
4843
@spec genesis_block_header_hash() :: term()
4944
def genesis_block_header_hash() do
5045
Block.genesis_block().header
5146
|> BlockValidation.block_header_hash()
5247
|> Base.encode16()
5348
end
5449

50+
@doc """
51+
Making async post requests to the users
52+
`type` is related to the uri e.g. /new_block
53+
"""
54+
@spec broadcast_to_all({type :: atom(), data :: term()}) :: :ok | :error
55+
def broadcast_to_all({type, data}) do
56+
data = prep_data(type,data)
57+
GenServer.cast(__MODULE__, {:broadcast_to_all, {type, data}})
58+
end
59+
60+
## Server side
61+
62+
def init(initial_peers) do
63+
{:ok, initial_peers}
64+
end
65+
5566
def handle_call({:add_peer,uri}, _from, peers) do
5667
case(Client.get_info(uri)) do
5768
{:ok, info} ->
@@ -88,8 +99,10 @@ defmodule Aecore.Peers.Worker do
8899
"""
89100
def handle_call(:check_peers, _from, peers) do
90101
filtered_peers = :maps.filter(fn(peer, _) ->
91-
{status, info} = Client.get_info(peer)
92-
:ok == status && info.genesis_block_hash == genesis_block_header_hash()
102+
case Client.get_info(peer) do
103+
{:ok, info} -> info.genesis_block_hash == genesis_block_header_hash()
104+
_ -> false
105+
end
93106
end, peers)
94107
updated_peers =
95108
for {peer, current_block_hash} <- filtered_peers, into: %{} do
@@ -109,17 +122,25 @@ defmodule Aecore.Peers.Worker do
109122
{:reply, peers, peers}
110123
end
111124

112-
def handle_cast({:broadcast_tx, tx}, peers) do
113-
serialized_tx =
114-
Serialization.tx(tx, :serialize)
115-
|> Poison.encode!()
116-
for peer <- peers do
117-
Client.send_tx(peer, serialized_tx)
118-
end
125+
## Async operations
119126

127+
def handle_cast({:broadcast_to_all, {type, data}}, peers) do
128+
send_to_peers(type, data, Map.keys(peers))
120129
{:noreply, peers}
121130
end
131+
122132
def handle_cast(_any, peers) do
123-
{:noreply, peers}
133+
Logger.info("[Peers] Unhandled cast message: #{inspect(peers)}")
124134
end
135+
136+
## Internal functions
137+
defp send_to_peers(uri, data, peers) do
138+
for peer <- peers do
139+
HttpClient.post(peer, data, uri)
140+
end
141+
end
142+
143+
defp prep_data(:new_tx, %{}=data), do: Serialization.tx(data, :serialize)
144+
defp prep_data(:new_block, %{}=data), do: Serialization.block(data, :serialize)
145+
125146
end

apps/aecore/lib/aecore/txs/pool/worker.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ defmodule Aecore.Txs.Pool.Worker do
99
alias Aecore.Keys.Worker, as: Keys
1010
alias Aecore.Structures.SignedTx
1111
alias Aecore.Peers.Worker, as: Peers
12+
1213
require Logger
1314

1415
def start_link do
@@ -44,8 +45,8 @@ defmodule Aecore.Txs.Pool.Worker do
4445
if is_tx_valid do
4546
updated_pool = Map.put_new(tx_pool, :crypto.hash(:sha256, :erlang.term_to_binary(tx)), tx)
4647
case tx_pool == updated_pool do
47-
true -> Logger.info(" This transaction has already been added")
48-
false -> Peers.broadcast_tx(tx)
48+
true -> Logger.info(" This transaction already has been added")
49+
false -> Peers.broadcast_to_all({:new_tx, tx})
4950
end
5051
{:reply, :ok, updated_pool}
5152
else

apps/aecore/lib/aecore/utils/serialization.ex

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ defmodule Aecore.Utils.Serialization do
44
"""
55

66
alias Aecore.Structures.Block
7+
alias Aecore.Structures.Header
8+
alias Aecore.Structures.TxData
79
alias Aecore.Structures.SignedTx
810

911
@spec block(%Block{}, :serialize | :deserialize) :: %Block{}
@@ -13,16 +15,16 @@ defmodule Aecore.Utils.Serialization do
1315
prev_hash: hex_binary(block.header.prev_hash, direction),
1416
txs_hash: hex_binary(block.header.txs_hash, direction)}
1517
new_txs = Enum.map(block.txs, fn(tx) -> tx(tx,direction) end)
16-
%{block | header: new_header, txs: new_txs}
18+
Block.new(%{block | header: Header.new(new_header), txs: new_txs})
1719
end
1820

1921
@spec tx(map(), :serialize | :deserialize) :: map() | {:error, term()}
2022
def tx(tx, direction) do
2123
new_data = %{tx.data |
22-
from_acc: hex_binary(tx.data.from_acc, direction),
23-
to_acc: hex_binary(tx.data.to_acc, direction)}
24+
from_acc: hex_binary(tx.data.from_acc, direction),
25+
to_acc: hex_binary(tx.data.to_acc, direction)}
2426
new_signature = hex_binary(tx.signature, direction)
25-
%SignedTx{data: new_data, signature: new_signature}
27+
%SignedTx{data: TxData.new(new_data), signature: new_signature}
2628
end
2729

2830
def hex_binary(data, direction) do

apps/aecore/test/aecore_pow_cuckoo_test.exs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ defmodule AecoreCuckooTest do
55
alias Aecore.Pow.Cuckoo
66
alias Aecore.Structures.Block
77

8-
@doctest Cuckoo
9-
108
@moduledoc """
119
Unit tests for the cuckoo module
1210
"""

apps/aehttpclient/lib/client.ex

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ defmodule Aehttpclient.Client do
1818
get(uri <> "/block/#{hash}", :block)
1919
end
2020

21+
def post(peer, data, uri) do
22+
send_to_peer(data, "#{peer}/#{uri}")
23+
end
24+
2125
@spec get_peers(term()) :: {:ok, list()}
2226
def get_peers(uri) do
2327
get(uri <> "/peers", :peers)
@@ -29,7 +33,6 @@ defmodule Aehttpclient.Client do
2933
Enum.each(peers, fn{peer, _} -> Peers.add_peer(peer) end)
3034
end
3135

32-
@spec get_account_balance({term(), term()}) :: {:ok, map()} | :error
3336
def get_account_balance({uri,acc}) do
3437
get(uri <> "/balance/#{acc}", :balance)
3538
end
@@ -63,17 +66,13 @@ defmodule Aehttpclient.Client do
6366
end
6467
end
6568

66-
@doc """
67-
Send newest transactions to a peer
68-
"""
69-
@spec send_tx(tuple(), map()) :: {:ok, map()} | {:error, term()}
70-
def send_tx({uri,_}, tx) do
71-
HTTPoison.post uri <> "/new_tx", Poison.encode!(tx),
72-
[{"Content-Type", "application/json"}]
73-
end
74-
7569
def json_response(body) do
7670
response = Poison.decode!(body)
7771
{:ok,response}
7872
end
73+
74+
defp send_to_peer(data, uri) do
75+
HTTPoison.post uri, Poison.encode!(data),
76+
[{"Content-Type", "application/json"}]
77+
end
7978
end

apps/aehttpclient/test/aehttpclient_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ defmodule AehttpclientTest do
1111
test "Client functions" do
1212
account = Keys.pubkey() |> elem(1) |> Base.encode16()
1313
add_txs_to_pool()
14-
genesis_block = Block.genesis_block()
14+
_genesis_block = Block.genesis_block()
1515
assert {:ok, _} = Client.get_info("localhost:4000")
16-
assert {:ok, genesis_block} = Client.get_block({"localhost:4000",
16+
assert {:ok, _genesis_block} = Client.get_block({"localhost:4000",
1717
"C061E48A6F7FB2634E0C012B168D41F4773A38BD9E5EA28E5BE7D04186127BA0"})
1818
assert {:ok, _} = Client.get_peers("localhost:4000")
1919
assert Enum.count(Client.get_account_txs({"localhost:4000", account})

apps/aehttpserver/config/prod.exs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ use Mix.Config
1212
# manifest is generated by the mix phoenix.digest task
1313
# which you typically run after static files are built.
1414
config :aehttpserver, Aehttpserver.Endpoint,
15-
http: [:inet6, port: {:system, "PORT"}],
16-
url: [host: "example.com", port: 80],
17-
cache_static_manifest: "priv/static/cache_manifest.json"
15+
http: [port: 4000],
16+
debug_errors: true,
17+
code_reloader: true,
18+
check_origin: false,
19+
watchers: []
1820

1921
# Do not print debug messages in production
2022
config :logger, level: :info

apps/aehttpserver/web/controllers/block_controller.ex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,15 @@ defmodule Aehttpserver.BlockController do
1515
json conn, %{error: message}
1616
end
1717
end
18+
19+
def new_block(conn, params) do
20+
## Becouse we 'conn.body_params' contains decoded json as map with
21+
## keys as strings instead of atoms we are doing this workaround
22+
map = Poison.decode!(Poison.encode!(conn.body_params), [keys: :atoms])
23+
24+
block = Aecore.Utils.Serialization.block(map, :deserialize)
25+
26+
Aecore.Chain.Worker.add_block(block)
27+
json conn, %{ok: "new block received"}
28+
end
1829
end

apps/aehttpserver/web/controllers/new_tx_controller.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ defmodule Aehttpserver.NewTxController do
44
alias Aecore.Utils.Serialization
55
alias Aecore.Txs.Pool.Worker, as: Pool
66

7+
78
def new_tx(conn, _params) do
8-
conn.body_params["_json"]
9+
## Simplest way to convert all keys in map to atoms is to
10+
## encode and decode it again.
11+
Poison.encode!(conn.body_params)
912
|> Poison.decode!([keys: :atoms])
1013
|> Serialization.tx(:deserialize)
1114
|> Pool.add_transaction()

0 commit comments

Comments
 (0)