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
35 changes: 20 additions & 15 deletions apps/aecore/lib/aecore/miner/worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule Aecore.Miner.Worker do
alias Aecore.Txs.Pool.Worker, as: Pool

@coinbase_transaction_value 100
@nonce_per_cycle 100000

def start_link() do
GenStateMachine.start_link(__MODULE__, %{}, name: __MODULE__)
Expand All @@ -39,10 +40,10 @@ defmodule Aecore.Miner.Worker do
end

## Idle ##
def idle({:call, from}, :start, data) do
def idle({:call, from}, :start, _data) do
IO.puts("Mining resuming by user")
GenStateMachine.cast(__MODULE__, :mine)
{:next_state, :running, data, [{:reply, from, :ok}]}
{:next_state, :running, 0, [{:reply, from, :ok}]}
end

def idle({:call, from}, :suspend, data) do
Expand All @@ -62,10 +63,10 @@ defmodule Aecore.Miner.Worker do
end

## Running ##
def running(:cast, :mine, data) do
mine_next_block()
def running(:cast, :mine, start_nonce) do
{_, next_nonce} = mine_next_block(start_nonce)
GenStateMachine.cast(__MODULE__, :mine)
{:next_state, :running, data}
{:next_state, :running, next_nonce}
end

def running({:call, from}, :get_state, _data) do
Expand Down Expand Up @@ -103,8 +104,8 @@ defmodule Aecore.Miner.Worker do
def coinbase_transaction_value, do: @coinbase_transaction_value

## Internal
@spec mine_next_block() :: :ok | :error
defp mine_next_block() do
@spec mine_next_block(integer()) :: :ok | :error
defp mine_next_block(start_nonce) do
chain_state = Chain.chain_state()

txs_list = Map.values(Pool.get_and_empty_pool())
Expand Down Expand Up @@ -139,13 +140,17 @@ defmodule Aecore.Miner.Worker do
Block.current_block_version()
)

{:ok, mined_header} = Hashcash.generate(unmined_header)
block = %Block{header: mined_header, txs: valid_txs}

Logger.info(fn ->
"Mined block ##{block.header.height}, difficulty target #{block.header.difficulty_target}, nonce #{block.header.nonce}"
end)

Chain.add_block(block)
case Hashcash.generate(unmined_header, start_nonce + @nonce_per_cycle) do
{:ok, mined_header} ->
block = %Block{header: mined_header, txs: valid_txs}
Chain.add_block(block)
Logger.info(fn ->
"Mined block ##{block.header.height}, difficulty target #{block.header.difficulty_target}, nonce #{block.header.nonce}"
end)
{:block_found, 0}

{:error, _message} ->
{:no_block_found, start_nonce + @nonce_per_cycle}
end
end
end
18 changes: 11 additions & 7 deletions apps/aecore/lib/aecore/pow/hashcash.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ defmodule Aecore.Pow.Hashcash do
@doc """
Find a nonce
"""
@spec generate(map()) :: {:ok, %Aecore.Structures.Header{}} | {:error, term()}
def generate(%Aecore.Structures.Header{nonce: nonce} = block_header) do
@spec generate(map(), integer()) :: {:ok, %Aecore.Structures.Header{}} | {:error, term()}
def generate(%Aecore.Structures.Header{nonce: nonce} = block_header, start_nonce) do
block_header_hash = BlockValidation.block_header_hash(block_header)

case verify(block_header_hash, block_header.difficulty_target) do
true -> {:ok, block_header}
false -> generate(%{block_header | nonce: nonce + 1})
end
case verify(block_header_hash, block_header.difficulty_target) do
true -> {:ok, block_header}
false ->
if(nonce <= start_nonce) do
generate(%{block_header | nonce: nonce + 1}, start_nonce)
else
{:error, "no solution found"}
end
end
end
end
3 changes: 2 additions & 1 deletion apps/aecore/test/aecore_hashcash_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ defmodule HashcashTest do

@tag timeout: 10000000
test "successfull test" do
assert {:ok, mined_header} = Hashcash.generate(Block.genesis_block.header)
start_nonce = 0
assert {:ok, mined_header} = Hashcash.generate(Block.genesis_block.header, start_nonce)
assert :true = Hashcash.verify(mined_header)
end
end