Skip to content

Commit

Permalink
Revert "revert: reverts ife deletion commits (#1725)"
Browse files Browse the repository at this point in the history
This reverts commit ed8b0f7.
  • Loading branch information
pgebal committed Sep 10, 2020
1 parent b8dea75 commit 5e23fd4
Show file tree
Hide file tree
Showing 16 changed files with 297 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "priv/cabbage"]
path = priv/cabbage
url = https://github.com/omgnetwork/specs.git
branch = master
branch = master
1 change: 1 addition & 0 deletions apps/omg_db/lib/db.ex
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ defmodule OMG.DB do
:last_exit_finalizer_eth_height,
:last_exit_challenger_eth_height,
:last_in_flight_exit_processor_eth_height,
:last_ife_exit_deleted_eth_height,
:last_piggyback_processor_eth_height,
:last_competitor_processor_eth_height,
:last_challenges_responds_processor_eth_height,
Expand Down
2 changes: 1 addition & 1 deletion apps/omg_eth/lib/omg_eth/root_chain/abi.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.
defmodule OMG.Eth.RootChain.Abi do
@moduledoc """
Functions that provide ethereum log decoding
Functions that provide ethereum log decoding
"""
alias OMG.Eth.Encoding
alias OMG.Eth.RootChain.AbiEventSelector
Expand Down
13 changes: 13 additions & 0 deletions apps/omg_eth/lib/omg_eth/root_chain/abi_event_selector.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ defmodule OMG.Eth.RootChain.AbiEventSelector do
}
end

@spec in_flight_exit_deleted() :: ABI.FunctionSelector.t()
def in_flight_exit_deleted() do
%ABI.FunctionSelector{
function: "InFlightExitDeleted",
input_names: ["exitId"],
inputs_indexed: [true],
method_id: <<25, 145, 196, 195>>,
returns: [],
type: :event,
types: [uint: 160]
}
end

@spec in_flight_exit_challenged() :: ABI.FunctionSelector.t()
def in_flight_exit_challenged() do
%ABI.FunctionSelector{
Expand Down
5 changes: 5 additions & 0 deletions apps/omg_eth/lib/omg_eth/root_chain/fields.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ defmodule OMG.Eth.RootChain.Fields do
reduce_naming(data, contracts_naming)
end

def rename(data, %ABI.FunctionSelector{function: "InFlightExitDeleted"}) do
contracts_naming = [{"exitId", :exit_id}]
reduce_naming(data, contracts_naming)
end

def rename(data, %ABI.FunctionSelector{function: "InFlightExitChallenged"}) do
contracts_naming = [
{"challenger", :challenger},
Expand Down
34 changes: 31 additions & 3 deletions apps/omg_eth/test/omg_eth/root_chain/abi_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,36 @@ defmodule OMG.Eth.RootChain.AbiTest do
}
end

test "if in flight exit finalized can be decoded" do
in_flight_exit_finalized_log = %{
test "if in flight exit deleted can be decoded" do
in_flight_exit_deleted_log = %{
:event_signature => "InFlightExitDeleted(uint160)",
"address" => "0x89afce326e7da55647d22e24336c6a2816c99f6b",
"blockHash" => "0xa27ed6299f3d74954e2c32629a5d807743627f8e57f83c8cbeaa4351da73f597",
"blockNumber" => "0x3e8",
"data" => "0x",
"logIndex" => "0x0",
"removed" => false,
"topics" => [
"0x1991c4c350498b0cc937c6a08bc5bdecf2e4fdd9d918052a880f102e43dbe45c",
"0x00000000000000000000000000d1d291fd21f1899f4c9d621f65dd1e0aa2355d"
],
"transactionHash" => "0xbe310ade41278c5607620311b79363aa520ac46c7ba754bf3027d501c5a95f40",
"transactionIndex" => "0x0"
}

assert Abi.decode_log(in_flight_exit_deleted_log) == %{
eth_height: 1000,
event_signature: "InFlightExitDeleted(uint160)",
exit_id: 4_679_199_003_952_701_118_642_806_135_853_996_264_334_177_629,
log_index: 0,
root_chain_txhash:
<<190, 49, 10, 222, 65, 39, 140, 86, 7, 98, 3, 17, 183, 147, 99, 170, 82, 10, 196, 108, 123, 167, 84,
191, 48, 39, 213, 1, 197, 169, 95, 64>>
}
end

test "if in flight exit output withdrawn can be decoded" do
in_flight_exit_output_withdrawn_log = %{
:event_signature => "InFlightExitOutputWithdrawn(uint160,uint16)",
"address" => "0x92ce4d7773c57d96210c46a07b89acf725057f21",
"blockHash" => "0x2218cd9358fd6ed3b720b512b645a88a9a3ed9f472e6192fae202f60e40ac7a2",
Expand All @@ -520,7 +548,7 @@ defmodule OMG.Eth.RootChain.AbiTest do
"transactionIndex" => "0x0"
}

assert Abi.decode_log(in_flight_exit_finalized_log) == %{
assert Abi.decode_log(in_flight_exit_output_withdrawn_log) == %{
eth_height: 335,
event_signature: "InFlightExitOutputWithdrawn(uint160,uint16)",
in_flight_exit_id: 3_853_567_223_408_339_354_111_409_210_931_346_801_537_991_844,
Expand Down
1 change: 1 addition & 0 deletions apps/omg_watcher/lib/omg_watcher/coordinator_setup.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ defmodule OMG.Watcher.CoordinatorSetup do
],
exit_challenger: [waits_for: :exit_processor, finality_margin: finality_margin],
in_flight_exit_processor: [waits_for: :depositor, finality_margin: finality_margin],
in_flight_exit_deleted_processor: [waits_for: :in_flight_exit_processor, finality_margin: finality_margin],
piggyback_processor: [waits_for: :in_flight_exit_processor, finality_margin: finality_margin],
competitor_processor: [waits_for: :in_flight_exit_processor, finality_margin: finality_margin],
challenges_responds_processor: [waits_for: :competitor_processor, finality_margin: finality_margin],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
defmodule OMG.Watcher.EthereumEventAggregator do
@moduledoc """
This process combines all plasma contract events we're interested in and does eth_getLogs + enriches them if needed
for all Ethereum Event Listener processes.
for all Ethereum Event Listener processes.
"""
use GenServer
require Logger
Expand Down Expand Up @@ -52,6 +52,11 @@ defmodule OMG.Watcher.EthereumEventAggregator do
forward_call(server, :in_flight_exit_started, from_block, to_block, @timeout)
end

@spec in_flight_exit_deleted(GenServer.server(), pos_integer(), pos_integer()) :: result()
def in_flight_exit_deleted(server \\ __MODULE__, from_block, to_block) do
forward_call(server, :in_flight_exit_deleted, from_block, to_block, @timeout)
end

@spec in_flight_exit_piggybacked(GenServer.server(), pos_integer(), pos_integer()) :: result()
def in_flight_exit_piggybacked(server \\ __MODULE__, from_block, to_block) do
# input and output
Expand Down
28 changes: 28 additions & 0 deletions apps/omg_watcher/lib/omg_watcher/exit_processor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ defmodule OMG.Watcher.ExitProcessor do
GenServer.call(__MODULE__, {:new_in_flight_exits, in_flight_exit_started_events}, @timeout)
end

@doc """
Accepts events and processes them in the state - new in flight exits are tracked.
Returns `db_updates` to be sent to `OMG.DB` by the caller
"""
# empty list clause to not block the server for no-ops
def delete_in_flight_exits([]), do: {:ok, []}

def delete_in_flight_exits(in_flight_exit_deleted_events) do
GenServer.call(__MODULE__, {:delete_in_flight_exits, in_flight_exit_deleted_events}, @timeout)
end

@doc """
Accepts events and processes them in the state - finalized exits are untracked _if valid_ otherwise raises alert
Expand Down Expand Up @@ -359,6 +371,22 @@ defmodule OMG.Watcher.ExitProcessor do
{:reply, {:ok, db_updates}, new_state}
end

@doc """
See `delete_in_flight_exits/1`. Flow:
- spends input utxos
- deletes in-flight exits from state
"""
def handle_call({:delete_in_flight_exits, deletions}, _from, state) do
_ =
if not Enum.empty?(deletions),
do: Logger.info("Recognized #{Enum.count(deletions)} deletions: #{inspect(deletions)}")

{new_state, deleted_utxos, db_updates} = Core.delete_in_flight_exits(state, deletions)
{:ok, db_updates_from_state, _validities} = State.exit_utxos(deleted_utxos)

{:reply, {:ok, db_updates ++ db_updates_from_state}, new_state}
end

@doc """
See `finalize_exits/1`. Flow:
Expand Down
28 changes: 28 additions & 0 deletions apps/omg_watcher/lib/omg_watcher/exit_processor/core.ex
Original file line number Diff line number Diff line change
Expand Up @@ -641,4 +641,32 @@ defmodule OMG.Watcher.ExitProcessor.Core do

defp sla_margin_safe?(exit_processor_sla_margin, min_exit_period_seconds, ethereum_block_time_seconds),
do: exit_processor_sla_margin * ethereum_block_time_seconds < min_exit_period_seconds

@doc """
Deletes in-flight exits from state and returns deleted exits
"""
@spec delete_in_flight_exits(__MODULE__.t(), list(map)) :: {__MODULE__.t(), list(InFlightExitInfo.t()), list(any())}
def delete_in_flight_exits(state, deletions) do
exit_ids =
deletions
|> Enum.map(fn %{exit_id: exit_id} -> InFlightExitInfo.to_contract_id(exit_id) end)
|> MapSet.new()

deleted_ifes_by_key =
state.in_flight_exits
|> Enum.filter(fn {_, ife} -> MapSet.member?(exit_ids, ife.contract_id) end)
|> Map.new()

deleted_keys = Map.keys(deleted_ifes_by_key)
updated_ifes = Map.drop(state.in_flight_exits, deleted_keys)

deleted_utxos =
deleted_ifes_by_key
|> Map.values()
|> InFlightExitInfo.get_input_utxos()

db_updates = Enum.map(deleted_keys, fn key -> {:delete, :in_flight_exit_info, key} end)

{%{state | in_flight_exits: updated_ifes}, deleted_utxos, db_updates}
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ defmodule OMG.Watcher.ExitProcessor.InFlightExitInfo do
{:put, :in_flight_exit_info, {ife_hash, value}}
end

@doc """
Returns all input utxos for given in-flight exits
"""
@spec get_input_utxos(list(t())) :: list(Utxo.Position.t())
def get_input_utxos(in_flight_exits) do
in_flight_exits
|> Enum.map(& &1.input_utxos_pos)
|> List.flatten()
end

defp assert_utxo_pos_type(Utxo.position(blknum, txindex, oindex))
when is_integer(blknum) and is_integer(txindex) and is_integer(oindex),
do: :ok
Expand Down Expand Up @@ -417,6 +427,12 @@ defmodule OMG.Watcher.ExitProcessor.InFlightExitInfo do
}),
do: is_older?(seen_in_pos, oldest_competitor_pos)

@doc """
Converts integer to in-flight exit contract id
"""
@spec to_contract_id(non_neg_integer) :: <<_::192>>
def to_contract_id(id), do: <<id::192>>

@doc """
Checks if the competitor being seen at `competitor_pos` (`nil` if unseen) is viable to challenge with, considering the
current state of the IFE - that is, only if it is older than IFE tx's inclusion and other competitors
Expand Down
10 changes: 10 additions & 0 deletions apps/omg_watcher/lib/omg_watcher/sync_supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ defmodule OMG.Watcher.SyncSupervisor do
[name: :exit_finalized, enrich: false],
[name: :exit_challenged, enrich: false],
[name: :in_flight_exit_started, enrich: true],
[name: :in_flight_exit_deleted, enrich: false],
[name: :in_flight_exit_input_piggybacked, enrich: false],
[name: :in_flight_exit_output_piggybacked, enrich: false],
[name: :in_flight_exit_challenged, enrich: true],
Expand Down Expand Up @@ -213,6 +214,15 @@ defmodule OMG.Watcher.SyncSupervisor do
get_events_callback: &EthereumEventAggregator.in_flight_exit_withdrawn/2,
process_events_callback: &Watcher.ExitProcessor.finalize_in_flight_exits/1
),
EthereumEventListener.prepare_child(
metrics_collection_interval: metrics_collection_interval,
ethereum_events_check_interval_ms: ethereum_events_check_interval_ms,
contract_deployment_height: contract_deployment_height,
service_name: :in_flight_exit_deleted_processor,
synced_height_update_key: :last_ife_exit_deleted_eth_height,
get_events_callback: &EthereumEventAggregator.in_flight_exit_deleted/2,
process_events_callback: &Watcher.ExitProcessor.delete_in_flight_exits/1
),
{StatusCache, [event_bus: OMG.Bus, ets: status_cache()]},
{ChildManager, [monitor: Monitor]}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
[name: :exit_started, enrich: true],
[name: :in_flight_exit_input_piggybacked, enrich: false],
[name: :in_flight_exit_output_piggybacked, enrich: false],
[name: :in_flight_exit_started, enrich: true]
[name: :in_flight_exit_started, enrich: true],
[name: :in_flight_exit_deleted, enrich: false]
]}
)

Expand Down Expand Up @@ -70,6 +71,11 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
event_fetcher_name: event_fetcher_name
} do
assert event_fetcher_name |> :sys.get_state() |> Map.get(:events) == [
[
signature: "InFlightExitDeleted(uint160)",
name: :in_flight_exit_deleted,
enrich: false
],
[
signature: "InFlightExitStarted(address,bytes32)",
name: :in_flight_exit_started,
Expand Down Expand Up @@ -107,6 +113,7 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
"InFlightExitOutputPiggybacked(address,bytes32,uint16)",
"InFlightExitInputPiggybacked(address,bytes32,uint16)",
"ExitStarted(address,uint160)",
"InFlightExitDeleted(uint160)",
"DepositCreated(address,uint256,address,uint256)"
])
end
Expand Down Expand Up @@ -225,7 +232,8 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
EthereumEventAggregatorTest.deposit_created_log(from_block + 1),
EthereumEventAggregatorTest.exit_started_log(to_block),
EthereumEventAggregatorTest.in_flight_exit_output_piggybacked_log(from_block),
EthereumEventAggregatorTest.in_flight_exit_input_piggybacked_log(to_block)
EthereumEventAggregatorTest.in_flight_exit_input_piggybacked_log(to_block),
EthereumEventAggregatorTest.in_flight_exit_deleted_log(from_block)
]}
end

Expand Down Expand Up @@ -255,6 +263,8 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do

in_flight_exit_output_piggybacked_log = from_block |> in_flight_exit_output_piggybacked_log() |> Abi.decode_log()
in_flight_exit_input_piggybacked_log = to_block |> in_flight_exit_input_piggybacked_log() |> Abi.decode_log()

exit_deleted = from_block |> in_flight_exit_deleted_log() |> Abi.decode_log()
# now we're asserting that the API returns the correct events based on the range
assert EthereumEventAggregator.exit_started(event_fetcher_name, from_block, to_block) == {:ok, [exit_started_log]}

Expand All @@ -264,10 +274,14 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
assert EthereumEventAggregator.deposit_created(event_fetcher_name, from_block, to_block) ==
{:ok, [deposit_created, deposit_created_2]}

assert EthereumEventAggregator.in_flight_exit_deleted(event_fetcher_name, from_block, to_block) ==
{:ok, [exit_deleted]}

# and now we're asserting that the API calls actually stored the events above
# also that the events were stored at the right blknum key
assert Enum.sort(:ets.tab2list(table)) ==
Enum.sort([
{from_block, get_signature_from_event(events, :in_flight_exit_deleted), [exit_deleted]},
{from_block, get_signature_from_event(events, :deposit_created), [deposit_created]},
{from_block, get_signature_from_event(events, :in_flight_exit_output_piggybacked),
[in_flight_exit_output_piggybacked_log]},
Expand All @@ -279,12 +293,14 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
{from_block + 1, get_signature_from_event(events, :in_flight_exit_started), []},
{from_block + 1, get_signature_from_event(events, :in_flight_exit_input_piggybacked), []},
{from_block + 1, get_signature_from_event(events, :exit_started), []},
{from_block + 1, get_signature_from_event(events, :in_flight_exit_deleted), []},
{to_block, get_signature_from_event(events, :deposit_created), []},
{to_block, get_signature_from_event(events, :in_flight_exit_output_piggybacked), []},
{to_block, get_signature_from_event(events, :exit_started), [exit_started_log]},
{to_block, get_signature_from_event(events, :in_flight_exit_input_piggybacked),
[in_flight_exit_input_piggybacked_log]},
{to_block, get_signature_from_event(events, :in_flight_exit_started), []}
{to_block, get_signature_from_event(events, :in_flight_exit_started), []},
{to_block, get_signature_from_event(events, :in_flight_exit_deleted), []}
])
end

Expand Down Expand Up @@ -337,6 +353,7 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do

assert Enum.sort(:ets.tab2list(table)) ==
Enum.sort([
{from_block, get_signature_from_event(events, :in_flight_exit_deleted), []},
{from_block, get_signature_from_event(events, :deposit_created), [deposit_created]},
{to_block, get_signature_from_event(events, :exit_started), [exit_started_log]},
{from_block, get_signature_from_event(events, :in_flight_exit_output_piggybacked),
Expand Down Expand Up @@ -529,6 +546,24 @@ defmodule OMG.Watcher.EthereumEventAggregatorTest do
}
end

def in_flight_exit_deleted_log(block_number) do
%{
:event_signature => "InFlightExitDeleted(uint160)",
"address" => "0x92ce4d7773c57d96210c46a07b89acf725057f21",
"blockHash" => "0xcafbc4b710c5fab8f3d719f65053637407231ecde31a859f1709e3478a2eda54",
"blockNumber" => "0x" <> Integer.to_string(block_number, 16),
"data" => "0x",
"logIndex" => "0x2",
"removed" => false,
"topics" => [
"0x1991c4c350498b0cc937c6a08bc5bdecf2e4fdd9d918052a880f102e43dbe45c",
"0x000000000000000000000000003fd275046f2823936fd97c1e3c8b225464d7f1"
],
"transactionHash" => "0xbe310ade41278c5607620311b79363aa520ac46c7ba754bf3027d501c5a95f40",
"transactionIndex" => "0x0"
}
end

def start_standard_exit_log() do
"0x70e014620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000001d1e4e4ea00000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000005df85b01c0f6f501f39408858124b3b880c68b360fd319cc61da27545e9a940000000000000000000000000000000000000000880de0b6b3a764000080a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200f39a869f62e75cf5f0bf914688a6b289caf2049435d8e68c5c5e6d05e44913f34ed5c02d6d48c8932486c99d3ad999e5d8949dc3be3b3058cc2979690c3e3a621c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35fd364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd07168d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849fde9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040ad516082324c96127cf29f4535eb5b7ebacfe2a1d6d3aab8ec0483d32079a859ff70f9215970a8beebb1c164c474e82438174c8eeb6fbc8cb4594b88c9448f1d40b09beaecac5b45db6e41434a122b695c5a85862d8eae40b3268f6f37e414337be38eba7ab5bbf303d01f4b7ae07fd73edc2f3be05e43948a34418a3272509c43c2811a821e5c982ba51874ac7dc9dd79a80cc2f05f6f664c9dbb2e454435137da06ce44de45532a56a3a7007a2d0c6b435f726f95104bfa6e707046fc154bae91898d03a1a0ac6f9b45e471646e2555ac79e3fe87eb1781e26f20500240c379274fe91096e60d1545a8045571fdab9b530d0d6e7e8746e78bf9f20f4e86f06"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,23 @@ defmodule OMG.Watcher.ExitProcessor.Core.StateInteractionTest do
assert [_] = Core.get_active_in_flight_exits(processor)
end

test "deleting in-flight exits works with State",
%{processor_empty: processor, state_empty: state, alice: alice} do
ife_exit_tx = TestHelper.create_recovered([{1, 0, 0, alice}], @eth, [{alice, 9}])
ife_id = 1

state = TestHelper.do_deposit(state, alice, %{amount: 10, currency: @eth, blknum: 1})
{:ok, _, state} = State.Core.form_block(state)

{_processor, deleted_utxos, _db_updates} =
processor
|> start_ife_from(ife_exit_tx, exit_id: ife_id)
|> Core.delete_in_flight_exits([%{exit_id: ife_id}])

assert {:ok, {[{:delete, :utxo, _}], {[{:utxo_position, 1, 0, 0}], []}}, _} =
State.Core.exit_utxos(deleted_utxos, state)
end

defp mock_utxo_exists(%ExitProcessor.Request{utxos_to_check: positions} = request, state) do
%{request | utxo_exists_result: positions |> Enum.map(&State.Core.utxo_exists?(&1, state))}
end
Expand Down
Loading

0 comments on commit 5e23fd4

Please sign in to comment.