Skip to content

Commit

Permalink
Add a sync_with_file mix task
Browse files Browse the repository at this point in the history
Other changes:

* Changed the genesis block nonce to a raw binary instead of an integer.
I compared our implementation with the genesis block from SyncWithInfura
which had it as a raw binary.
  • Loading branch information
masonforest committed Sep 25, 2018
1 parent bf7f7a4 commit a90ae7a
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .dialyzer.ignore-warnings
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ apps/blockchain/lib/blockchain/transaction.ex
-------------------------------
apps/blockchain/lib/blockchain/application.ex:14: The call 'Elixir.EVM.Debugger':break_on([{'address',binary()},...]) will never return since the success typing is (['address']) -> integer() and the contract is (elixir:keyword('Elixir.EVM.Debugger.Breakpoint':conditions())) -> 'Elixir.EVM.Debugger.Breakpoint':id()

-------------------------------
# apps/blockchain/lib/mix/tasks/sync/from_file.ex
-------------------------------
apps/blockchain/lib/mix/tasks/sync/from_file.ex
-------------------------------
# Ignores the whole contract and account_interface file
-------------------------------
Expand Down
2 changes: 1 addition & 1 deletion apps/blockchain/lib/blockchain/chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ defmodule Blockchain.Chain do

defp get_genesis_seal(map) do
%{
nonce: map["ethereum"]["nonce"] |> load_hex(),
nonce: map["ethereum"]["nonce"] |> load_raw_hex(),
mix_hash: map["ethereum"]["mixHash"] |> load_raw_hex()
}
end
Expand Down
2 changes: 1 addition & 1 deletion apps/blockchain/lib/blockchain/genesis.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ defmodule Blockchain.Genesis do
receipts_root: <<86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33>>,
ommers_hash: <<29, 204, 77, 232, 222, 199, 93, 122, 171, 133, 181, 103, 182, 204, 212, 26, 211, 18, 69, 27, 148, 138, 116, 19, 240, 161, 66, 253, 64, 212, 147, 71>>,
mix_hash: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
nonce: 66
nonce: <<0, 0, 0, 0, 0, 0, 0, 66>>
},
ommers: [],
transactions: []
Expand Down
86 changes: 86 additions & 0 deletions apps/blockchain/lib/mix/tasks/sync/from_file.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
defmodule Mix.Tasks.Sync.FromFile do
@shortdoc "Allows users to sync the blockchain from a file exported by parity"
@moduledoc """
SyncFromFile allows users to sync the blockchain from a file exported by parity.
You can make an export with the following command:
`parity export blocks ./export-blocks-mainnet.bin`
And then run `sync_with_file` to verify the chain:
`mix run apps/blockchain/scripts/sync_from_file.ex export-blocks-mainnet.bin`
"""
use Mix.Task
require Logger

def run(args) do
{db, chain} = setup()

current_block_number =
case MerklePatriciaTree.DB.get(db, "current_block_number") do
{:ok, current_block_number} ->
current_block_number

_ ->
0
end

tree =
case MerklePatriciaTree.DB.get(db, "current_block_tree") do
{:ok, current_block_tree} ->
:erlang.binary_to_term(current_block_tree)

_ ->
Blockchain.Blocktree.new_tree()
end

{first_block_data, blocks_data} =
args
|> File.read!()
|> ExRLP.decode()
|> Enum.split(3)

first_block = Blockchain.Block.deserialize(first_block_data)

blocks =
[Blockchain.Genesis.create_block(chain, db), first_block] ++
(blocks_data
|> Enum.map(&Blockchain.Block.deserialize/1))

add_block_to_tree(db, chain, tree, blocks, current_block_number)
end

def setup() do
db = MerklePatriciaTree.DB.RocksDB.init(db_name())
chain = Blockchain.Chain.load_chain(:foundation)

{db, chain}
end

def add_block_to_tree(db, chain, tree, blocks, n) do
next_block = Enum.at(blocks, n)

if is_nil(next_block) do
Logger.info("Validation complete")
MerklePatriciaTree.DB.put!(db, "current_block_number", 0)
else
case Blockchain.Blocktree.verify_and_add_block(tree, chain, next_block, db) do
{:ok, next_tree} ->
Logger.info("Verified Block #{n}")
MerklePatriciaTree.DB.put!(db, "current_block_number", next_block.header.number)
add_block_to_tree(db, chain, next_tree, blocks, n + 1)

{:invalid, error} ->
Logger.info("Failed to Verify Block #{n}")
Logger.error(inspect(error))
MerklePatriciaTree.DB.put!(db, "current_block_tree", :erlang.term_to_binary(tree))
end
end
end

defp db_name() do
env = Mix.env() |> to_string()
"db/mana-" <> env
end
end

0 comments on commit a90ae7a

Please sign in to comment.