From 031c32315612351dabee6d63dd82b7ddd875645f Mon Sep 17 00:00:00 2001 From: Bastien CHAMAGNE Date: Tue, 24 Jan 2023 14:31:00 +0100 Subject: [PATCH 1/3] ActionInterpreter.execute might return nil to not create a next tx --- lib/archethic/contracts/interpreter/action.ex | 14 ++++++++---- lib/archethic/contracts/worker.ex | 22 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/archethic/contracts/interpreter/action.ex b/lib/archethic/contracts/interpreter/action.ex index 077c77e4b..d252b095c 100644 --- a/lib/archethic/contracts/interpreter/action.ex +++ b/lib/archethic/contracts/interpreter/action.ex @@ -321,11 +321,11 @@ defmodule Archethic.Contracts.ActionInterpreter do end @doc """ - Execute actions code and returns a transaction as result + Execute actions code and returns either the next transaction or nil """ - @spec execute(Macro.t(), map()) :: Transaction.t() + @spec execute(Macro.t(), map()) :: Transaction.t() | nil def execute(code, constants \\ %{}) do - {%{"next_transaction" => next_transaction}, _} = + result = Code.eval_quoted(code, scope: Map.put(constants, "next_transaction", %Transaction{ @@ -333,6 +333,12 @@ defmodule Archethic.Contracts.ActionInterpreter do }) ) - next_transaction + case result do + {%{"next_transaction" => next_transaction}, _} -> + next_transaction + + _ -> + nil + end end end diff --git a/lib/archethic/contracts/worker.ex b/lib/archethic/contracts/worker.ex index ff3269e1c..7906c22f5 100644 --- a/lib/archethic/contracts/worker.ex +++ b/lib/archethic/contracts/worker.ex @@ -103,11 +103,16 @@ defmodule Archethic.Contracts.Worker do contract_transaction = Constants.to_transaction(contract_constants) with true <- ConditionInterpreter.valid_conditions?(transaction_condition, constants), - next_tx <- ActionInterpreter.execute(Map.fetch!(triggers, :transaction), constants), + next_tx when not is_nil(next_tx) <- + ActionInterpreter.execute(Map.fetch!(triggers, :transaction), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction) do handle_new_transaction(next_tx) {:noreply, state} else + nil -> + # contract did not create a next tx + {:noreply, state} + false -> Logger.debug("Incoming transaction didn't match the condition", transaction_address: Base.encode16(incoming_tx.address), @@ -150,7 +155,7 @@ defmodule Archethic.Contracts.Worker do contract_tx = Constants.to_transaction(contract_constants) - with next_tx <- + with next_tx when not is_nil(next_tx) <- ActionInterpreter.execute(Map.fetch!(triggers, {:datetime, timestamp}), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_tx) do handle_new_transaction(next_tx) @@ -184,7 +189,7 @@ defmodule Archethic.Contracts.Worker do contract_transaction = Constants.to_transaction(contract_constants) with true <- enough_funds?(address), - next_tx <- + next_tx when not is_nil(next_tx) <- ActionInterpreter.execute(Map.fetch!(triggers, {:interval, interval}), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction), :ok <- ensure_enough_funds(next_tx, address) do @@ -218,18 +223,25 @@ defmodule Archethic.Contracts.Worker do contract_transaction = Constants.to_transaction(contract_constants) if Conditions.empty?(oracle_condition) do - with next_tx <- ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants), + with next_tx when not is_nil(next_tx) <- + ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction), :ok <- ensure_enough_funds(next_tx, address) do handle_new_transaction(next_tx) end else with true <- ConditionInterpreter.valid_conditions?(oracle_condition, constants), - next_tx <- ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants), + next_tx when not is_nil(next_tx) <- + ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction), :ok <- ensure_enough_funds(next_tx, address) do handle_new_transaction(next_tx) else + nil -> + Logger.error("Oracle contract did not trigger a new tx", + contract: Base.encode16(address) + ) + false -> Logger.error("Invalid oracle conditions", contract: Base.encode16(address)) From 16ffe482ed19341fb5d21b642fe017e4843498a1 Mon Sep 17 00:00:00 2001 From: Bastien CHAMAGNE Date: Wed, 25 Jan 2023 18:24:19 +0100 Subject: [PATCH 2/3] lint: pattern match on struct instead of not nil --- lib/archethic/contracts/worker.ex | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/archethic/contracts/worker.ex b/lib/archethic/contracts/worker.ex index 7906c22f5..6aca064b0 100644 --- a/lib/archethic/contracts/worker.ex +++ b/lib/archethic/contracts/worker.ex @@ -103,14 +103,14 @@ defmodule Archethic.Contracts.Worker do contract_transaction = Constants.to_transaction(contract_constants) with true <- ConditionInterpreter.valid_conditions?(transaction_condition, constants), - next_tx when not is_nil(next_tx) <- + next_tx = %Transaction{} <- ActionInterpreter.execute(Map.fetch!(triggers, :transaction), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction) do handle_new_transaction(next_tx) {:noreply, state} else nil -> - # contract did not create a next tx + # returned by ActionInterpreter.execute when contract did not create a next tx {:noreply, state} false -> @@ -155,7 +155,7 @@ defmodule Archethic.Contracts.Worker do contract_tx = Constants.to_transaction(contract_constants) - with next_tx when not is_nil(next_tx) <- + with next_tx = %Transaction{} <- ActionInterpreter.execute(Map.fetch!(triggers, {:datetime, timestamp}), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_tx) do handle_new_transaction(next_tx) @@ -189,7 +189,7 @@ defmodule Archethic.Contracts.Worker do contract_transaction = Constants.to_transaction(contract_constants) with true <- enough_funds?(address), - next_tx when not is_nil(next_tx) <- + next_tx = %Transaction{} <- ActionInterpreter.execute(Map.fetch!(triggers, {:interval, interval}), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction), :ok <- ensure_enough_funds(next_tx, address) do @@ -223,7 +223,7 @@ defmodule Archethic.Contracts.Worker do contract_transaction = Constants.to_transaction(contract_constants) if Conditions.empty?(oracle_condition) do - with next_tx when not is_nil(next_tx) <- + with next_tx = %Transaction{} <- ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction), :ok <- ensure_enough_funds(next_tx, address) do @@ -231,13 +231,14 @@ defmodule Archethic.Contracts.Worker do end else with true <- ConditionInterpreter.valid_conditions?(oracle_condition, constants), - next_tx when not is_nil(next_tx) <- + next_tx = %Transaction{} <- ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants), {:ok, next_tx} <- chain_transaction(next_tx, contract_transaction), :ok <- ensure_enough_funds(next_tx, address) do handle_new_transaction(next_tx) else nil -> + # returned by ActionInterpreter.execute when contract did not create a next tx Logger.error("Oracle contract did not trigger a new tx", contract: Base.encode16(address) ) From 06e95b4833273891fc163b7e17ec21147f807595 Mon Sep 17 00:00:00 2001 From: Bastien CHAMAGNE Date: Tue, 31 Jan 2023 14:27:15 +0100 Subject: [PATCH 3/3] reduce log severity + remove the error log --- lib/archethic/contracts/worker.ex | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/archethic/contracts/worker.ex b/lib/archethic/contracts/worker.ex index 6aca064b0..3725aa614 100644 --- a/lib/archethic/contracts/worker.ex +++ b/lib/archethic/contracts/worker.ex @@ -239,15 +239,13 @@ defmodule Archethic.Contracts.Worker do else nil -> # returned by ActionInterpreter.execute when contract did not create a next tx - Logger.error("Oracle contract did not trigger a new tx", - contract: Base.encode16(address) - ) + :ok false -> - Logger.error("Invalid oracle conditions", contract: Base.encode16(address)) + Logger.info("Invalid oracle conditions", contract: Base.encode16(address)) {:error, e} -> - Logger.error("#{inspect(e)}", contract: Base.encode16(address)) + Logger.info("#{inspect(e)}", contract: Base.encode16(address)) end end end