Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moonbeam interface impl #32

Merged
merged 14 commits into from
Oct 4, 2023
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
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "CI"
on: ["push", "pull_request"]

jobs:
test_and_build:
name: "Build and lint"
runs-on: "ubuntu-latest"
steps:
- name: Install deps
run: sudo apt-get install -y libboost-dev libboost-system-dev

- name: Setup elixir
uses: erlef/setup-elixir@v1
with:
otp-version: 24.3.3
elixir-version: 1.13.4

- uses: actions/checkout@v1
- run: |
mix local.hex --force
mix local.rebar --force
mix deps.get
mix lint
# mix test
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
python 3.9.18
erlang 25.3
21 changes: 0 additions & 21 deletions .travis.yml

This file was deleted.

14 changes: 10 additions & 4 deletions deployment/fabfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,27 @@ def install():
#put(".inputrc", "~")

# Elixir + Base System
if not exists("/usr/bin/elixir"):
run("wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb")
run("dpkg -i erlang-solutions_1.0_all.deb")
if not exists("~/.asdf/asdf.sh"):
run("apt update")
run("apt upgrade -y")
run("apt install -y screen git snap g++ make autoconf esl-erlang elixir libtool libgmp-dev daemontools libboost-system-dev libsqlite3-dev")
run("apt install -y libncurses-dev screen git snap g++ make unzip autoconf libtool libgmp-dev daemontools libboost-system-dev libsqlite3-dev")
run("apt autoremove")

run("git clone https://github.com/asdf-vm/asdf.git ~/.asdf")
run("echo '. ~/.asdf/asdf.sh' >> ~/.bashrc")
run(". ~/.asdf/asdf.sh && asdf plugin add erlang")
run(". ~/.asdf/asdf.sh && asdf plugin add elixir")

# Application
run("mkdir -p {}".format(env.diode))
with cd(env.diode):
run("git init")
run("git config receive.denyCurrentBranch ignore")
local("git push -f ssh://{user}@{host}{path} master".format(user=env.user, host=env.host, path=env.diode))
run("git checkout master")
#run("echo 'elixir 1.14' > .tool-versions")
#run("echo 'erlang 24.0.4' >> .tool-versions")
#run("export KERL_CONFIGURE_OPTIONS=--without-wx && . ~/.asdf/asdf.sh && asdf install")
run("cp githooks/post-receive .git/hooks/")
run("cp deployment/diode.service /etc/systemd/system/diode.service")
run("HOME=`pwd` mix local.hex --force")
Expand Down
28 changes: 0 additions & 28 deletions docker

This file was deleted.

60 changes: 7 additions & 53 deletions lib/chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,16 @@ defmodule Chain do
def init(ets_extra) do
_create(ets_extra)
BlockProcess.start_link()

OnCrash.call(fn reason ->
Logger.error("Chain exited with reason #{inspect(reason)}. Halting system")
System.halt(1)
end)

OnCrash.call(&on_crash/1)
{:ok, load_blocks()}
end

@spec on_crash(any()) :: no_return()
def on_crash(reason) do
Logger.error("Chain exited with reason #{inspect(reason)}. Halting system")
System.halt(1)
end

def window_size() do
100
end
Expand Down Expand Up @@ -370,53 +371,6 @@ defmodule Chain do
fun.(state, from)
end

def export_blocks(filename \\ "block_export.sq3", blocks \\ Chain.blocks()) do
Sqlitex.with_db(filename, fn db ->
Sqlitex.query!(db, """
CREATE TABLE IF NOT EXISTS block_export (
number INTEGER PRIMARY KEY,
data BLOB
) WITHOUT ROWID;
""")

start =
case Sqlitex.query!(db, "SELECT MAX(number) as max FROM block_export") do
[[max: nil]] -> 0
[[max: max]] -> max
end

IO.puts("start: #{start}")

Stream.take_while(blocks, fn block -> Block.number(block) > start end)
|> Stream.chunk_every(100)
|> Task.async_stream(fn blocks ->
IO.puts("Writing block #{Block.number(hd(blocks))}")

Enum.map(blocks, fn block ->
data =
Block.export(block)
|> BertInt.encode!()

[Block.number(block), data]
end)
end)
|> Stream.each(fn {:ok, blocks} ->
:ok = Sqlitex.exec(db, "BEGIN")

Enum.each(blocks, fn [num, data] ->
Sqlitex.query!(
db,
"INSERT INTO block_export (number, data) VALUES(?1, CAST(?2 AS BLOB))",
bind: [num, data]
)
end)

:ok = Sqlitex.exec(db, "COMMIT")
end)
|> Stream.run()
end)
end

defp decode_blocks("") do
[]
end
Expand Down
1 change: 0 additions & 1 deletion lib/chain/block.ex
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,6 @@ defmodule Chain.Block do
case last_final(block) do
block = %Block{} -> Block.hash(block)
hash when is_binary(hash) -> hash
nil -> nil
end
end

Expand Down
11 changes: 9 additions & 2 deletions lib/diode.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ defmodule Diode do
end

puts("Data Dir : #{data_dir()}")

if System.get_env("COOKIE") do
:erlang.set_cookie(String.to_atom(System.get_env("COOKIE")))
puts("Cookie : #{System.get_env("COOKIE")}")
end

puts("")

if dev_mode?() and [] == wallets() do
Expand Down Expand Up @@ -77,11 +83,12 @@ defmodule Diode do
worker(Stats, []),
supervisor(Model.Sql),
supervisor(Channels),
worker(PubSub, [args]),
worker(Chain.BlockCache, [ets_extra]),
worker(Chain, [ets_extra]),
worker(PubSub, [args]),
worker(Chain.Pool, [args]),
worker(TicketStore, [ets_extra])
worker(TicketStore, [ets_extra]),
worker(Moonbeam.NonceProvider)
]

children =
Expand Down
98 changes: 98 additions & 0 deletions lib/eip712.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
defmodule EIP712 do
defstruct [:primary_type, :types, :message]

def encode(domain_separator, primary_type, type_data, message) do
Hash.keccak_256(
"\x19\x01" <> domain_separator <> hash_struct(primary_type, type_data, message)
)
end

# Special case for a flat EIP712 (no nested user types)
def encode(domain_separator, primary_type, message) do
{types, values} = split_fields(message)
encode(domain_separator, primary_type, %{primary_type => types}, values)
end

def encode_type(primary_type, type_data) do
prefix = encode_single_type(primary_type, Map.get(type_data, primary_type))

types =
Enum.map(type_data[primary_type], fn
{_name, type} -> type
{_name, type, _value} -> type
end)
|> Enum.uniq()

postfix =
Enum.filter(type_data, fn
{name, _} -> name != primary_type and name in types
end)
|> Enum.map(fn {name, fields} -> encode_single_type(name, fields) end)
|> Enum.sort()
|> Enum.join()

prefix <> postfix
end

def encode_single_type(type, fields) do
names =
Enum.map(fields, fn
{name, type} -> "#{type} #{name}"
{name, type, _value} -> "#{type} #{name}"
end)

type <> "(" <> Enum.join(names, ",") <> ")"
end

def type_hash(primary_type, type_data) when is_map(type_data) do
encode_type(primary_type, type_data) |> Hash.keccak_256()
end

@spec hash_struct(binary(), [{String.t(), String.t(), any()}]) :: binary()
def hash_struct(primary_type, type_data) do
{types, values} = split_fields(type_data)
hash_struct(primary_type, %{primary_type => types}, values)
end

def hash_struct(primary_type, type_data, message) do
encode_data =
Enum.map(type_data[primary_type], fn {name, type} when is_binary(type) ->
value = Map.get(message, name)

cond do
type == "bytes" or type == "string" ->
ABI.encode("bytes32", Hash.keccak_256(value))

Map.has_key?(type_data, type) ->
hash_struct(type, type_data, value)

true ->
ABI.encode(type, value)
end
end)
|> Enum.join()

Hash.keccak_256(type_hash(primary_type, type_data) <> encode_data)
end

def hash_domain_separator(name, version, chain_id, verifying_contract)
when is_binary(name) and is_binary(version) and is_integer(chain_id) and
is_binary(verifying_contract) do
hash_struct("EIP712Domain", [
{"name", "string", name},
{"version", "string", version},
{"chainId", "uint256", chain_id},
{"verifyingContract", "address", verifying_contract}
])
end

defp split_fields(fields) do
{types, values} =
Enum.map(fields, fn {name, type, value} ->
{{name, type}, {name, value}}
end)
|> Enum.unzip()

{types, Map.new(values)}
end
end
7 changes: 0 additions & 7 deletions lib/kademlia.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ defmodule Kademlia do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__, hibernate_after: 5_000)
end

@spec ping(any) :: any
def ping(node_id) do
rpc(find_node(node_id), [Client.ping()])
end
Expand All @@ -51,7 +50,6 @@ defmodule Kademlia do
@doc """
store/1 same as store/2 but usees Object.key/1 and Object.encode/1
"""
@spec store(tuple()) :: any()
def store(object) when is_tuple(object) do
key = Object.key(object)
value = Object.encode!(object)
Expand All @@ -62,7 +60,6 @@ defmodule Kademlia do
store() stores the given key-value pair in the @k nodes
that are closest to the key
"""
@spec store(binary(), binary()) :: any()
def store(key, value) when is_binary(value) do
nodes =
find_nodes(key)
Expand All @@ -76,7 +73,6 @@ defmodule Kademlia do
find_value() is different from store() in that it might return
an earlier result
"""
@spec find_value(binary()) :: any()
def find_value(key) do
key = hash(key)
nodes = do_find_nodes(key, KBuckets.k(), Client.find_value())
Expand Down Expand Up @@ -132,7 +128,6 @@ defmodule Kademlia do
end
end

@spec find_node(Wallet.address()) :: nil | KBuckets.Item.t()
def find_node(address) do
case find_nodes(address) do
[] ->
Expand All @@ -146,7 +141,6 @@ defmodule Kademlia do
end
end

@spec find_nodes(any()) :: [KBuckets.Item.t()]
def find_nodes(key) do
key = hash(key)
visited = do_find_nodes(key, KBuckets.k(), Client.find_node())
Expand Down Expand Up @@ -175,7 +169,6 @@ defmodule Kademlia do
Retrieves for the target key either the last cached values or
the nearest k entries from the KBuckets store
"""
@spec find_node_lookup(any()) :: [KBuckets.Item.t()]
def find_node_lookup(key) do
get_cached(&nearest_n/1, key)
end
Expand Down
Loading
Loading