Skip to content

Commit

Permalink
SC: ActionInterpreter.execute might return nil to not create a next tx (
Browse files Browse the repository at this point in the history
#863)

* ActionInterpreter.execute might return nil to not create a next tx

* lint: pattern match on struct instead of not nil

* reduce log severity + remove the error log
  • Loading branch information
bchamagne committed Feb 1, 2023
1 parent a83f265 commit 4cc5bae
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
14 changes: 10 additions & 4 deletions lib/archethic/contracts/interpreter/action.ex
Original file line number Diff line number Diff line change
Expand Up @@ -341,18 +341,24 @@ 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{
data: %TransactionData{}
})
)

next_transaction
case result do
{%{"next_transaction" => next_transaction}, _} ->
next_transaction

_ ->
nil
end
end
end
25 changes: 18 additions & 7 deletions lib/archethic/contracts/worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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 = %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 ->
# returned by ActionInterpreter.execute when 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),
Expand Down Expand Up @@ -150,7 +155,7 @@ defmodule Archethic.Contracts.Worker do

contract_tx = Constants.to_transaction(contract_constants)

with 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)
Expand Down Expand Up @@ -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 = %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
Expand Down Expand Up @@ -218,23 +223,29 @@ 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 = %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)
end
else
with true <- ConditionInterpreter.valid_conditions?(oracle_condition, constants),
next_tx <- ActionInterpreter.execute(Map.fetch!(triggers, :oracle), constants),
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
: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
Expand Down

0 comments on commit 4cc5bae

Please sign in to comment.