Skip to content

Commit

Permalink
Merge branch 'develop' into return_hash
Browse files Browse the repository at this point in the history
  • Loading branch information
apoorv-2204 committed Dec 2, 2022
2 parents bb070f8 + 0d5fbd6 commit f5cffd9
Show file tree
Hide file tree
Showing 84 changed files with 5,254 additions and 2,925 deletions.
2 changes: 0 additions & 2 deletions .dialyzer_ignore.exs

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ jobs:
mkdir -p priv/plts
mix dialyzer --plt
- name: Run dialyzer
run: mix dialyzer --no-check
run: mix dialyzer --no-check --ignore-exit-status
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ compile_c_programs:
mkdir -p priv/c_dist
$(CC) src/c/crypto/stdio_helpers.c src/c/crypto/ed25519.c -o priv/c_dist/libsodium_port -I src/c/crypto/stdio_helpers.h -lsodium
$(CC) src/c/hypergeometric_distribution.c -o priv/c_dist/hypergeometric_distribution -lgmp

git submodule update --force --recursive --init --remote
$(MAKE) -C src/c/nat/miniupnp/miniupnpc
cp src/c/nat/miniupnp/miniupnpc/build/upnpc-static priv/c_dist/upnpc


ifeq ($(TPM_INSTALLED),0)
$(CC) src/c/crypto/stdio_helpers.c src/c/crypto/tpm/lib.c src/c/crypto/tpm/port.c -o priv/c_dist/tpm_port -I src/c/crypto/stdio_helpers.h -I src/c/crypto/tpm/lib.h $(TPMFLAGS)
Expand All @@ -24,6 +24,7 @@ endif
clean:
rm -f priv/c_dist/*
mix archethic.clean_db
mix clean

docker-clean: clean
docker container stop $$(docker ps -a --filter=name=utn* -q)
Expand Down
1 change: 1 addition & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config :git_hooks,
pre_push: [
tasks: [
{:cmd, "mix clean"},
{:cmd, "mix git_hooks.install"},
{:cmd, "mix hex.outdated --within-requirements"},
{:cmd, "mix format --check-formatted"},
{:cmd, "mix compile --warnings-as-errors"},
Expand Down
4 changes: 1 addition & 3 deletions lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ defmodule Archethic do
alias __MODULE__.P2P
alias __MODULE__.P2P.Node

alias __MODULE__.DB

alias __MODULE__.P2P.Message.Balance
alias __MODULE__.P2P.Message.GetBalance
alias __MODULE__.P2P.Message.NewTransaction
Expand Down Expand Up @@ -275,7 +273,7 @@ defmodule Archethic do
try do
{local_chain, paging_address} =
with true <- paging_address != nil,
true <- DB.transaction_exists?(paging_address),
true <- TransactionChain.transaction_exists?(paging_address),
last_address when last_address != nil <-
TransactionChain.get_last_local_address(address),
true <- last_address != paging_address do
Expand Down
4 changes: 2 additions & 2 deletions lib/archethic/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ defmodule Archethic.Account do
@doc """
Load the transaction into the Account context filling the memory tables for ledgers
"""
@spec load_transaction(Transaction.t()) :: :ok
defdelegate load_transaction(transaction), to: MemTablesLoader
@spec load_transaction(Transaction.t(), boolean()) :: :ok
defdelegate load_transaction(transaction, io_transaction?), to: MemTablesLoader
end
51 changes: 32 additions & 19 deletions lib/archethic/account/mem_tables_loader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@ defmodule Archethic.Account.MemTablesLoader do

@spec init(args :: list()) :: {:ok, []}
def init(_args) do
TransactionChain.list_io_transactions(@query_fields)
|> Stream.each(&load_transaction(&1, true))
|> Stream.run()

TransactionChain.list_all(@query_fields)
|> Stream.reject(&(&1.type in @excluded_types))
|> Stream.each(&load_transaction/1)
|> Stream.each(&load_transaction(&1, false))
|> Stream.run()

{:ok, []}
Expand All @@ -67,25 +71,30 @@ defmodule Archethic.Account.MemTablesLoader do
@doc """
Load the transaction into the memory tables
"""
@spec load_transaction(Transaction.t()) :: :ok
def load_transaction(%Transaction{
address: address,
type: tx_type,
previous_public_key: previous_public_key,
validation_stamp: %ValidationStamp{
timestamp: timestamp,
protocol_version: protocol_version,
ledger_operations: %LedgerOperations{
fee: fee,
unspent_outputs: unspent_outputs,
transaction_movements: transaction_movements
@spec load_transaction(Transaction.t(), boolean()) :: :ok
def load_transaction(
%Transaction{
address: address,
type: tx_type,
previous_public_key: previous_public_key,
validation_stamp: %ValidationStamp{
timestamp: timestamp,
protocol_version: protocol_version,
ledger_operations: %LedgerOperations{
fee: fee,
unspent_outputs: unspent_outputs,
transaction_movements: transaction_movements
}
}
}
}) do
previous_address = Crypto.derive_address(previous_public_key)

UCOLedger.spend_all_unspent_outputs(previous_address)
TokenLedger.spend_all_unspent_outputs(previous_address)
},
io_transaction?
) do
unless io_transaction? do
previous_address = Crypto.derive_address(previous_public_key)

UCOLedger.spend_all_unspent_outputs(previous_address)
TokenLedger.spend_all_unspent_outputs(previous_address)
end

burn_storage_nodes =
Election.storage_nodes(
Expand Down Expand Up @@ -153,6 +162,10 @@ defmodule Archethic.Account.MemTablesLoader do
}
} ->
TokenLedger.add_unspent_output(address, unspent_output)

_ ->
# Ignore smart contract calls
:ignore
end)
end

Expand Down
9 changes: 1 addition & 8 deletions lib/archethic/beacon_chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -320,17 +320,10 @@ defmodule Archethic.BeaconChain do
end

defp get_summary_address_by_node(date, subset, authorized_nodes) do
# Remove the newly authorized nodes at this specific time
filter_nodes =
case authorized_nodes do
[node] -> [node]
nodes -> Enum.filter(nodes, &(DateTime.compare(&1.authorization_date, date) == :lt))
end

summary_address = Crypto.derive_beacon_chain_address(subset, date, true)

subset
|> Election.beacon_storage_nodes(date, filter_nodes)
|> Election.beacon_storage_nodes(date, authorized_nodes)
|> Enum.map(fn node ->
{node, summary_address}
end)
Expand Down
7 changes: 1 addition & 6 deletions lib/archethic/beacon_chain/subset.ex
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,7 @@ defmodule Archethic.BeaconChain.Subset do
end

defp broadcast_beacon_slot(subset, next_time, slot) do
# Remove the newly authorized nodes at this specific time
nodes =
case P2P.authorized_and_available_nodes(next_time) do
[node] -> [node]
nodes -> Enum.filter(nodes, &(DateTime.compare(&1.authorization_date, next_time) == :lt))
end
nodes = P2P.authorized_and_available_nodes(next_time, true)

subset
|> Election.beacon_storage_nodes(next_time, nodes)
Expand Down
44 changes: 23 additions & 21 deletions lib/archethic/contracts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ defmodule Archethic.Contracts do
"""

alias __MODULE__.Contract
alias __MODULE__.Contract.Conditions
alias __MODULE__.Contract.Constants
alias __MODULE__.Contract.Trigger
alias __MODULE__.ContractConditions, as: Conditions
alias __MODULE__.ContractConstants, as: Constants
alias __MODULE__.ConditionInterpreter
alias __MODULE__.Interpreter
alias __MODULE__.Loader
alias __MODULE__.TransactionLookup
Expand Down Expand Up @@ -59,9 +59,8 @@ defmodule Archethic.Contracts do
contract: nil,
transaction: nil
},
triggers: [
%Trigger{
actions: {:__block__, [], [
triggers: %{
{:datetime, ~U[2020-09-25 13:18:43Z]} => {:__block__, [], [
{
:=,
[line: 7],
Expand All @@ -79,11 +78,9 @@ defmodule Archethic.Contracts do
]
}
]},
opts: [at: ~U[2020-09-25 13:18:43Z]],
type: :datetime
}
]
}}
}
}
"""
@spec parse(binary()) :: {:ok, Contract.t()} | {:error, binary()}
def parse(contract_code) when is_binary(contract_code) do
Expand All @@ -100,11 +97,10 @@ defmodule Archethic.Contracts do
})

cond do
Enum.any?(triggers, &(&1.type == :transaction)) and
Conditions.empty?(transaction_conditions) ->
Map.has_key?(triggers, :transaction) and Conditions.empty?(transaction_conditions) ->
{:error, "missing transaction conditions"}

Enum.any?(triggers, &(&1.type == :oracle)) and Conditions.empty?(oracle_conditions) ->
Map.has_key?(triggers, :oracle) and Conditions.empty?(oracle_conditions) ->
{:error, "missing oracle conditions"}

true ->
Expand Down Expand Up @@ -168,18 +164,20 @@ defmodule Archethic.Contracts do
end

defp validate_conditions(inherit_conditions, constants) do
if Interpreter.valid_conditions?(inherit_conditions, constants) do
if ConditionInterpreter.valid_conditions?(inherit_conditions, constants) do
:ok
else
Logger.error("Inherit constraints not respected")
{:error, :invalid_inherit_constraints}
end
end

defp validate_triggers([], _, _), do: :ok
defp validate_triggers(triggers, _next_tx, _date) when map_size(triggers) == 0, do: :ok

defp validate_triggers(triggers, next_tx, date) do
if Enum.any?(triggers, &valid_from_trigger?(&1, next_tx, date)) do
if Enum.any?(triggers, fn {trigger_type, _} ->
valid_from_trigger?(trigger_type, next_tx, date)
end) do
:ok
else
Logger.error("Transaction not processed by a valid smart contract trigger")
Expand All @@ -188,7 +186,7 @@ defmodule Archethic.Contracts do
end

defp valid_from_trigger?(
%Trigger{type: :datetime, opts: [at: datetime]},
{:datetime, datetime},
%Transaction{},
validation_date = %DateTime{}
) do
Expand All @@ -198,21 +196,25 @@ defmodule Archethic.Contracts do
end

defp valid_from_trigger?(
%Trigger{type: :interval, opts: [at: interval]},
{:interval, interval},
%Transaction{},
validation_date = %DateTime{}
) do
interval
|> CronParser.parse!(true)
|> CronParser.parse!()
|> CronDateChecker.matches_date?(DateTime.to_naive(validation_date))
end

defp valid_from_trigger?(%Trigger{type: :transaction}, _, _), do: true
defp valid_from_trigger?(_, _, _), do: true

@doc """
List the address of the transaction which has contacted a smart contract
"""
@spec list_contract_transactions(binary()) :: list({binary(), DateTime.t()})
@spec list_contract_transactions(contract_address :: binary()) ::
list(
{transaction_address :: binary(), transaction_timestamp :: DateTime.t(),
protocol_version :: non_neg_integer()}
)
defdelegate list_contract_transactions(address),
to: TransactionLookup,
as: :list_contract_transactions
Expand Down
54 changes: 16 additions & 38 deletions lib/archethic/contracts/contract.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ defmodule Archethic.Contracts.Contract do
Represents a smart contract
"""

alias Archethic.Contracts.Contract.Conditions
alias Archethic.Contracts.Contract.Constants
alias Archethic.Contracts.Contract.Trigger
alias Archethic.Contracts.ContractConditions, as: Conditions
alias Archethic.Contracts.ContractConstants, as: Constants

alias Archethic.Contracts.Interpreter

Expand All @@ -14,7 +13,7 @@ defmodule Archethic.Contracts.Contract do
alias Archethic.TransactionChain.Transaction
alias Archethic.TransactionChain.TransactionData

defstruct triggers: [],
defstruct triggers: %{},
conditions: %{
transaction: %Conditions{},
inherit: %Conditions{},
Expand All @@ -23,12 +22,15 @@ defmodule Archethic.Contracts.Contract do
constants: %Constants{},
next_transaction: %Transaction{data: %TransactionData{}}

@type trigger_type() :: :datetime | :interval | :transaction
@type trigger_type() ::
{:datetime, DateTime.t()} | {:interval, String.t()} | :transaction | :oracle
@type condition() :: :transaction | :inherit | :oracle
@type origin_family :: SharedSecrets.origin_family()

@type t() :: %__MODULE__{
triggers: list(Trigger.t()),
triggers: %{
trigger_type() => Macro.t()
},
conditions: %{
transaction: Conditions.t(),
inherit: Conditions.t(),
Expand All @@ -55,48 +57,24 @@ defmodule Archethic.Contracts.Contract do
@doc """
Add a trigger to the contract
"""
@spec add_trigger(t(), Trigger.type(), Keyword.t(), Macro.t()) :: t()
@spec add_trigger(map(), trigger_type(), Macro.t()) :: t()
def add_trigger(
contract = %__MODULE__{},
:datetime,
opts = [at: _datetime = %DateTime{}],
type,
actions
) do
do_add_trigger(contract, %Trigger{type: :datetime, opts: opts, actions: actions})
end

def add_trigger(
contract = %__MODULE__{},
:interval,
opts = [at: interval],
actions
)
when is_binary(interval) do
do_add_trigger(contract, %Trigger{type: :interval, opts: opts, actions: actions})
end

def add_trigger(contract = %__MODULE__{}, :transaction, _, actions) do
do_add_trigger(contract, %Trigger{type: :transaction, actions: actions})
end

def add_trigger(contract = %__MODULE__{}, :oracle, _, actions) do
do_add_trigger(contract, %Trigger{type: :oracle, actions: actions})
end

defp do_add_trigger(contract, trigger = %Trigger{}) do
Map.update!(contract, :triggers, &(&1 ++ [trigger]))
Map.update!(contract, :triggers, &Map.put(&1, type, actions))
end

@doc """
Add a condition to the contract
"""
@spec add_condition(t(), condition(), any()) :: t()
@spec add_condition(map(), condition(), Conditions.t()) :: t()
def add_condition(
contract = %__MODULE__{conditions: conditions},
contract = %__MODULE__{},
condition_name,
condition
)
when condition_name in [:transaction, :inherit, :oracle] do
%{contract | conditions: Map.put(conditions, condition_name, condition)}
conditions = %Conditions{}
) do
Map.update!(contract, :conditions, &Map.put(&1, condition_name, conditions))
end
end
Loading

0 comments on commit f5cffd9

Please sign in to comment.