From 631783c5434c6402fa9eb70fb72770eed23d25ef Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 19 Aug 2022 17:59:00 +0200 Subject: [PATCH] Restrict oracle txs --- .../mining/pending_transaction_validation.ex | 23 +++++++++++++------ lib/archethic/oracle_chain.ex | 21 +++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/archethic/mining/pending_transaction_validation.ex b/lib/archethic/mining/pending_transaction_validation.ex index 54cfa321e4..d5e36f153c 100644 --- a/lib/archethic/mining/pending_transaction_validation.ex +++ b/lib/archethic/mining/pending_transaction_validation.ex @@ -355,16 +355,25 @@ defmodule Archethic.Mining.PendingTransactionValidation do end end - defp do_accept_transaction(%Transaction{ - type: :oracle, - data: %TransactionData{ - content: content + defp do_accept_transaction( + tx = %Transaction{ + type: :oracle, + data: %TransactionData{ + content: content + } } - }) do - if OracleChain.valid_services_content?(content) do + ) do + last_scheduling_date = OracleChain.get_last_scheduling_date(DateTime.utc_now()) + + with :ok <- validate_scheduling_network_tx_time(last_scheduling_date, tx), + true <- OracleChain.valid_services_content?(content) do :ok else - {:error, "Invalid oracle transaction"} + {:error, :time} -> + {:error, "Invalid oracle trigger time "} + + false -> + {:error, "Invalid oracle transaction"} end end diff --git a/lib/archethic/oracle_chain.ex b/lib/archethic/oracle_chain.ex index 7b2fb050de..0c2443b414 100644 --- a/lib/archethic/oracle_chain.ex +++ b/lib/archethic/oracle_chain.ex @@ -143,4 +143,25 @@ defmodule Archethic.OracleChain do |> CronScheduler.get_next_run_date!(DateTime.to_naive(date_from)) |> DateTime.from_naive!("Etc/UTC") end + + @doc """ + Get the previous polling date from the given date + """ + @spec get_last_scheduling_date(DateTime.t()) :: DateTime.t() + def get_last_scheduling_date(from_date = %DateTime{}) do + polling_interval = + Application.get_env(:archethic, Scheduler) + |> Keyword.fetch!(:polling_interval) + + cron_expression = Crontab.CronExpression.Parser.parse!(polling_interval, true) + naive_from_date = from_date |> DateTime.truncate(:second) |> DateTime.to_naive() + + if Crontab.DateChecker.matches_date?(cron_expression, naive_from_date) do + DateTime.truncate(from_date, :millisecond) + else + cron_expression + |> Crontab.Scheduler.get_previous_run_date!(naive_from_date) + |> DateTime.from_naive!("Etc/UTC") + end + end end