Skip to content

Commit

Permalink
blacklist methods using tagging
Browse files Browse the repository at this point in the history
  • Loading branch information
herissondev committed Aug 7, 2023
1 parent e743a06 commit ee4ec8a
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 13 deletions.
52 changes: 46 additions & 6 deletions lib/archethic/contracts/interpreter/function_interpreter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule Archethic.Contracts.Interpreter.FunctionInterpreter do
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST
alias Archethic.Contracts.Interpreter.Scope
alias Archethic.Contracts.Interpreter.CommonInterpreter
alias Knigge
require Logger

@doc """
Expand All @@ -18,7 +19,7 @@ defmodule Archethic.Contracts.Interpreter.FunctionInterpreter do
{:ok, function_name, args, ast}
catch
{:error, node} ->
{:error, node, "unexpectted term"}
{:error, node, "unexpected term"}

{:error, node, reason} ->
{:error, node, reason}
Expand All @@ -35,14 +36,14 @@ defmodule Archethic.Contracts.Interpreter.FunctionInterpreter do
{:ok, function_name, args, ast}
catch
{:error, node} ->
{:error, node, "unexpecccccted term"}
{:error, node, "unexpected term"}

{:error, node, reason} ->
{:error, node, reason}
end

def parse(node, _) do
{:error, node, "unexpecteeeeed term"}
{:error, node, "unexpected term"}
end

@doc """
Expand Down Expand Up @@ -97,11 +98,50 @@ defmodule Archethic.Contracts.Interpreter.FunctionInterpreter do
# ----------------------------------------------------------------------
# Ban access to Contract module
defp prewalk(
node = {:__aliases__, _, [atom: "Contract"]},
_,
node =
{{:., _meta, [{:__aliases__, _, [atom: "Contract"]}, {:atom, function_name}]}, _, _},
acc,
_visibility
) do
throw({:error, node, "Contract is not allowed in function"})
absolute_module_atom =
Code.ensure_loaded!(
String.to_existing_atom("Elixir.Archethic.Contracts.Interpreter.Library.Contract")
)

if absolute_module_atom.tagged_with?(String.to_atom(function_name), :write_contract) do
throw({:error, node, "Write contract functions are not allowed in custom functions"})
end

CommonInterpreter.prewalk(node, acc)
end

defp prewalk(
node =
{{:., _meta, [{:__aliases__, _, [atom: module_name]}, {:atom, function_name}]}, _, _},
acc,
true
) do
absolute_module_atom =
Code.ensure_loaded!(
String.to_existing_atom(
"Elixir.Archethic.Contracts.Interpreter.Library.Common.#{module_name}"
)
)

absolute_module_atom =
try do
%Knigge.Options{default: module} = Knigge.options!(absolute_module_atom)
module
rescue
_ ->
absolute_module_atom
end

if absolute_module_atom.tagged_with?(String.to_atom(function_name), :io) do
throw({:error, node, "IO function calls not allowed in public functions"})
end

CommonInterpreter.prewalk(node, acc)
end

defp prewalk(node = {{:atom, function_name}, _, args}, _acc, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.ChainImpl do
alias Archethic.Contracts.Interpreter.Library.Common.Chain
alias Archethic.Contracts.Interpreter.Legacy.UtilsInterpreter
alias Archethic.Contracts.ContractConstants, as: Constants

alias Archethic.Tag
alias Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperations

@behaviour Chain
use Tag

@tag [:io]
@impl Chain
defdelegate get_genesis_address(address),
to: Legacy.Library,
as: :get_genesis_address

@tag [:io]
@impl Chain
def get_first_transaction_address(address) do
try do
Expand All @@ -24,6 +27,7 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.ChainImpl do
end
end

@tag [:io]
@impl Chain
def get_genesis_public_key(public_key) do
try do
Expand All @@ -33,6 +37,7 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.ChainImpl do
end
end

@tag [:io]
@impl Chain
def get_transaction(address) do
address
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/code.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Code do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST

use Tag

@spec is_same?(binary(), binary()) :: boolean()
def is_same?(first_code, second_code) do
first_ast = first_code |> Interpreter.sanitize_code(ignore_meta?: true)
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/crypto.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Crypto do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST
alias Archethic.Contracts.Interpreter.Legacy
alias Archethic.Contracts.Interpreter.Legacy.UtilsInterpreter

use Tag

@spec hash(binary(), binary()) :: binary()
def hash(content, algo \\ "sha256")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.HttpImpl do
other processes, we use it from inside a Task.
"""

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.Library
alias Archethic.Contracts.Interpreter.Library.Common.Http
alias Archethic.TaskSupervisor

use Tag

@behaviour Http
@threshold 256 * 1024
@timeout Application.compile_env(:archethic, [__MODULE__, :timeout], 2_000)

@tag [:io]
@impl Http
def fetch(uri) do
task =
Expand Down Expand Up @@ -45,6 +49,7 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.HttpImpl do
end
end

@tag [:io]
@impl Http
def fetch_many(uris) do
uris_count = length(uris)
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/json.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Json do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST
alias Archethic.Contracts.Interpreter.Legacy

use Tag

@spec path_extract(String.t(), String.t()) :: String.t()
defdelegate path_extract(text, path),
to: Legacy.Library,
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.List do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST

use Tag

@spec at(list(), integer() | float()) :: any()
def at(list, idx) do
cond do
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/map.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Map do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST

use Tag

@spec new() :: map()
defdelegate new(),
to: Map
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/regex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Regex do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST
alias Archethic.Contracts.Interpreter.Legacy

use Tag

@spec match?(binary(), binary()) :: boolean()
defdelegate match?(text, pattern),
to: Legacy.Library,
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/string.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.String do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.ASTHelper, as: AST

use Tag

@spec size(String.t()) :: integer()
defdelegate size(str),
to: String,
Expand Down
3 changes: 3 additions & 0 deletions lib/archethic/contracts/interpreter/library/common/time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Time do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.Scope

use Tag

@doc """
Returns the Unix timestamp of the trigger (it is approximately the same as current time).
We cannot use "now" because it is not determinist.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.TokenImpl do
@moduledoc false
@behaviour Archethic.Contracts.Interpreter.Library.Common.Token

alias Archethic.Tag
alias Archethic.Contracts.Interpreter.Legacy

use Tag

@tag [:io]
@impl Archethic.Contracts.Interpreter.Library.Common.Token
defdelegate fetch_id_from_address(address),
to: Legacy.Library,
Expand Down
14 changes: 14 additions & 0 deletions lib/archethic/contracts/interpreter/library/contract.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ defmodule Archethic.Contracts.Interpreter.Library.Contract do
alias Archethic.TransactionChain.Transaction
alias Archethic.Contracts.Interpreter.Legacy.TransactionStatements
alias Archethic.Utils
alias Archethic.Tag

use Tag

@tag [:write_contract]
@spec set_type(Transaction.t(), binary()) :: Transaction.t()
defdelegate set_type(next_tx, type),
to: TransactionStatements

@tag [:write_contract]
@spec set_content(Transaction.t(), binary() | integer() | float()) :: Transaction.t()
def set_content(next_tx, content) when is_binary(content) do
put_in(next_tx, [Access.key(:data), Access.key(:content)], content)
Expand All @@ -29,45 +34,54 @@ defmodule Archethic.Contracts.Interpreter.Library.Contract do
)
end

@tag [:write_contract]
@spec set_code(Transaction.t(), binary()) :: Transaction.t()
defdelegate set_code(next_tx, args),
to: TransactionStatements

@tag [:write_contract]
@spec add_recipient(Transaction.t(), binary()) :: Transaction.t()
defdelegate add_recipient(next_tx, args),
to: TransactionStatements

@tag [:write_contract]
@spec add_recipients(Transaction.t(), list(binary())) :: Transaction.t()
defdelegate add_recipients(next_tx, args),
to: TransactionStatements

@tag [:write_contract]
@spec add_uco_transfer(Transaction.t(), map()) :: Transaction.t()
def add_uco_transfer(next_tx, args) do
args = Map.update!(args, "amount", &Utils.to_bigint/1)
TransactionStatements.add_uco_transfer(next_tx, Map.to_list(args))
end

@tag [:write_contract]
@spec add_uco_transfers(Transaction.t(), list(map())) :: Transaction.t()
def add_uco_transfers(next_tx, args) do
Enum.reduce(args, next_tx, &add_uco_transfer(&2, &1))
end

@tag [:write_contract]
@spec add_token_transfer(Transaction.t(), map()) :: Transaction.t()
def add_token_transfer(next_tx, args) do
args = Map.update!(args, "amount", &Utils.to_bigint/1)
TransactionStatements.add_token_transfer(next_tx, Map.to_list(args))
end

@tag [:write_contract]
@spec add_token_transfers(Transaction.t(), list(map())) :: Transaction.t()
def add_token_transfers(next_tx, args) do
Enum.reduce(args, next_tx, &add_token_transfer(&2, &1))
end

@tag [:write_contract]
@spec add_ownership(Transaction.t(), map()) :: Transaction.t()
def add_ownership(next_tx, args) do
TransactionStatements.add_ownership(next_tx, Map.to_list(args))
end

@tag [:write_contract]
@spec add_ownerships(Transaction.t(), list(map())) :: Transaction.t()
def add_ownerships(next_tx, args) do
casted_args = Enum.map(args, &Map.to_list/1)
Expand Down
Loading

0 comments on commit ee4ec8a

Please sign in to comment.