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
70 changes: 54 additions & 16 deletions apps/aecore/lib/aecore/chain/worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ defmodule Aecore.Chain.Worker do
genesis_block_map = %{genesis_block_hash => Block.genesis_block()}
genesis_chain_state = ChainState.calculate_block_state(Block.genesis_block().txs)
latest_block_chain_state = %{genesis_block_hash => genesis_chain_state}

initial_state = {genesis_block_map, latest_block_chain_state}
txs_index = calculate_block_acc_txs_info(Block.genesis_block())
initial_state = {genesis_block_map, latest_block_chain_state, txs_index}

{:ok, initial_state}
end
Expand Down Expand Up @@ -70,13 +70,18 @@ defmodule Aecore.Chain.Worker do
GenServer.call(__MODULE__, {:chain_state, latest_block_hash})
end

@spec txs_index() :: map()
def txs_index() do
GenServer.call(__MODULE__, :txs_index)
end

def handle_call(:get_latest_block_chain_state, _from, state) do
{_, latest_block_chain_state} = state
{_, latest_block_chain_state, _} = state
{:reply, latest_block_chain_state, state}
end

def handle_call({:get_block, block_hash}, _from, state) do
{block_map, _} = state
{block_map, _, _} = state
block = block_map[block_hash]

if(block != nil) do
Expand All @@ -87,7 +92,7 @@ defmodule Aecore.Chain.Worker do
end

def handle_call({:get_block_by_hex_hash, hash}, _from, state) do
{chain, _} = state
{chain, _, _} = state
case(Enum.find(chain, fn{block_hash, _block} ->
block_hash |> Base.encode16() == hash end)) do
{_, block} ->
Expand All @@ -98,17 +103,19 @@ defmodule Aecore.Chain.Worker do
end

def handle_call({:add_block, %Block{} = block}, _from, state) do
{chain, chain_state} = state
prev_block_chain_state = chain_state[block.header.prev_hash]
{block_map, latest_block_chain_state, txs_index} = state
prev_block_chain_state = latest_block_chain_state[block.header.prev_hash]
new_block_state = ChainState.calculate_block_state(block.txs)
new_chain_state = ChainState.calculate_chain_state(new_block_state, prev_block_chain_state)
new_chain_state =
ChainState.calculate_chain_state(new_block_state, prev_block_chain_state)

new_block_txs_index = calculate_block_acc_txs_info(block)
new_txs_index = update_txs_index(txs_index, new_block_txs_index)
try do
BlockValidation.validate_block!(block, chain[block.header.prev_hash], new_chain_state)
BlockValidation.validate_block!(block, block_map[block.header.prev_hash], new_chain_state)

Enum.each(block.txs, fn(tx) -> Pool.remove_transaction(tx) end)

{block_map, latest_block_chain_state} = state
block_hash = BlockValidation.block_header_hash(block.header)
updated_block_map = Map.put(block_map, block_hash, block)
has_prev_block = Map.has_key?(latest_block_chain_state, block.header.prev_hash)
Expand All @@ -121,10 +128,8 @@ defmodule Aecore.Chain.Worker do
{latest_block_chain_state, %{}}
end

new_block_state = ChainState.calculate_block_state(block.txs)
new_chain_state = ChainState.calculate_chain_state(new_block_state, prev_chain_state)

updated_latest_block_chainstate = Map.put(deleted_latest_chain_state, block_hash, new_chain_state)
updated_latest_block_chainstate =
Map.put(deleted_latest_chain_state, block_hash, new_chain_state)

total_tokens = ChainState.calculate_total_tokens(new_chain_state)

Expand All @@ -137,7 +142,7 @@ defmodule Aecore.Chain.Worker do
## Block was validated, now we can send it to other peers
Peers.broadcast_to_all({:new_block, block})

{:reply, :ok, {updated_block_map, updated_latest_block_chainstate}}
{:reply, :ok, {updated_block_map, updated_latest_block_chainstate, new_txs_index}}
catch
{:error, message} ->
Logger.error(fn ->
Expand All @@ -148,10 +153,15 @@ defmodule Aecore.Chain.Worker do
end

def handle_call({:chain_state, latest_block_hash}, _from, state) do
{_, chain_state} = state
{_, chain_state, _} = state
{:reply, chain_state[latest_block_hash], state}
end

def handle_call(:txs_index, _from, state) do
{_, _, txs_index} = state
{:reply, txs_index, state}
end

def chain_state() do
latest_block = latest_block()
latest_block_hash = BlockValidation.block_header_hash(latest_block.header)
Expand All @@ -164,6 +174,34 @@ defmodule Aecore.Chain.Worker do
get_blocks(latest_block_hash, latest_block_obj.header.height)
end

def calculate_block_acc_txs_info(block) do
block_hash = BlockValidation.block_header_hash(block.header)
accounts = for tx <- block.txs do
[tx.data.from_acc, tx.data.to_acc]
end
accounts = accounts |> List.flatten() |> Enum.uniq() |> List.delete(nil)
for account <- accounts, into: %{} do
acc_txs = Enum.filter(block.txs, fn(tx) ->
tx.data.from_acc == account || tx.data.to_acc == account
end)
tx_hashes = Enum.map(acc_txs, fn(tx) ->
tx_bin = :erlang.term_to_binary(tx)
:crypto.hash(:sha256, tx_bin)
end)
tx_tuples = Enum.map(tx_hashes, fn(hash) ->
{block_hash, hash}
end)
{account, tx_tuples}
end
end

def update_txs_index(current_txs_index, new_block_txs_index) do
Map.merge(current_txs_index, new_block_txs_index,
fn(_, current_list, new_block_list) ->
current_list ++ new_block_list
end)
end

defp get_blocks(blocks_acc, next_block_hash, size) do
cond do
size > 0 ->
Expand Down
4 changes: 1 addition & 3 deletions apps/aehttpclient/test/aehttpclient_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ defmodule AehttpclientTest do

use ExUnit.Case

alias Aecore.Structures.Block
alias Aecore.Chain.Worker, as: Chain
alias Aecore.Txs.Pool.Worker, as: Pool
alias Aecore.Keys.Worker, as: Keys
Expand All @@ -11,9 +10,8 @@ defmodule AehttpclientTest do
test "Client functions" do
account = Keys.pubkey() |> elem(1) |> Base.encode16()
add_txs_to_pool()
_genesis_block = Block.genesis_block()
assert {:ok, _} = Client.get_info("localhost:4000")
assert {:ok, _genesis_block} = Client.get_block({"localhost:4000",
assert {:ok, _} = Client.get_block({"localhost:4000",
"C061E48A6F7FB2634E0C012B168D41F4773A38BD9E5EA28E5BE7D04186127BA0"})
assert {:ok, _} = Client.get_peers("localhost:4000")
assert Enum.count(Client.get_account_txs({"localhost:4000", account})
Expand Down