Skip to content

Commit

Permalink
Prevent OracleSummary transaction to be submitted twice (#99)
Browse files Browse the repository at this point in the history
* Start timer only when there are not previous timer

* Start Oracle summary transaction only when there are no previous oracle summary transaction on the chain
  • Loading branch information
Samuel committed Sep 23, 2021
1 parent 5347432 commit 5b770b9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
31 changes: 25 additions & 6 deletions lib/archethic/oracle_chain/scheduler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ defmodule ArchEthic.OracleChain.Scheduler do
GenServer.start_link(__MODULE__, args, opts)
end

def start_scheduling do
GenServer.cast(__MODULE__, :start_scheduling)
end

def init(args) do
polling_interval = Keyword.fetch!(args, :polling_interval)
summary_interval = Keyword.fetch!(args, :summary_interval)
Expand All @@ -55,7 +51,8 @@ defmodule ArchEthic.OracleChain.Scheduler do
state = %{polling_interval: polling_interval, summary_interval: summary_interval}
) do
with ^first_public_key <- Crypto.first_node_public_key(),
nil <- Map.get(state, :polling_timer) do
nil <- Map.get(state, :polling_timer),
nil <- Map.get(state, :summary_timer) do
polling_timer = schedule_new_polling(polling_interval)
summary_timer = schedule_new_summary(summary_interval)

Expand Down Expand Up @@ -121,7 +118,14 @@ defmodule ArchEthic.OracleChain.Scheduler do

date = DateTime.utc_now() |> DateTime.truncate(:second)

if trigger_node?(date) do
# Because the time to schedule the transaction can variate in milliseconds,
# a node could have stored an OracleSummary transaction but still
# receiving a message to create a new summary transaction.
# And this would be valid because the second didn't finished yet.
# So to prevent an new oracle summary, we are fetching the last transaction on the chain.
# If it's not a oracle_summary, then we can propose the summary transaction
with true <- last_transaction_not_summary?(date),
true <- trigger_node?(date) do
Task.Supervisor.start_child(TaskSupervisor, fn ->
handle_new_summary(date)
end)
Expand Down Expand Up @@ -211,6 +215,21 @@ defmodule ArchEthic.OracleChain.Scheduler do
|> TransactionChain.size()
end

defp last_transaction_not_summary?(date = %DateTime{}) do
last_tx_address =
date
|> Crypto.derive_oracle_address(0)
|> TransactionChain.get_last_address()

case TransactionChain.get_transaction(last_tx_address, [:type]) do
{:ok, %Transaction{type: :oracle_summary}} ->
false

_ ->
true
end
end

defp get_oracle_data(address) do
case TransactionChain.get_transaction(address, data: [:content]) do
{:ok, %Transaction{data: %TransactionData{content: previous_content}}} ->
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule ArchEthic.MixProject do
def project do
[
app: :archethic,
version: "0.12.1",
version: "0.12.2",
build_path: "_build",
config_path: "config/config.exs",
deps_path: "deps",
Expand Down

0 comments on commit 5b770b9

Please sign in to comment.