From 54411722022acc9b6534d398adfc661dca0cb932 Mon Sep 17 00:00:00 2001 From: bchamagne <74045243+bchamagne@users.noreply.github.com> Date: Thu, 26 Jan 2023 12:34:23 +0100 Subject: [PATCH] SC: add get_calls/0 action (#822) * smart contract new action: get_inputs/1 * get_inputs handle both address formats * add the tx's content to the inputs * transform get_inputs/1 to get_calls/1 * move a function to utils * write the transaction call in DB before executing the worker * quick refactor get_calls after feedback * wip * SC: add get_calls/0 * un-whitelist get_calls/1 * Fix conflict * refactor: get_io_transaction return a result Co-authored-by: Neylix --- lib/archethic/contracts/interpreter/action.ex | 28 ++++++ .../contracts/interpreter/library.ex | 46 +++++----- .../interpreter/transaction_statements.ex | 32 +++---- lib/archethic/contracts/interpreter/utils.ex | 16 ++++ lib/archethic/contracts/loader.ex | 5 +- lib/archethic/db.ex | 4 + lib/archethic/db/embedded_impl.ex | 18 +++- .../db/embedded_impl/chain_reader.ex | 15 ++++ lib/archethic/transaction_chain.ex | 4 +- test/archethic/bootstrap_test.exs | 2 +- .../contracts/interpreter/action_test.exs | 86 +++++++++++++++++++ .../contracts/interpreter/library_test.exs | 9 +- test/archethic/contracts/worker_test.exs | 2 +- .../shared_secrets/software_impl_test.exs | 2 +- .../pending_transaction_validation_test.exs | 10 +-- .../archethic/oracle_chain/scheduler_test.exs | 2 +- test/archethic/replication_test.exs | 4 +- .../self_repair/self_repair_test.exs | 2 +- test/archethic_web/live/rewards_live_test.exs | 2 +- test/support/template.ex | 1 + 20 files changed, 231 insertions(+), 59 deletions(-) diff --git a/lib/archethic/contracts/interpreter/action.ex b/lib/archethic/contracts/interpreter/action.ex index 077c77e4b..44946c318 100644 --- a/lib/archethic/contracts/interpreter/action.ex +++ b/lib/archethic/contracts/interpreter/action.ex @@ -138,6 +138,14 @@ defmodule Archethic.Contracts.ActionInterpreter do {node, {:ok, %{context | scope: {:function, function, parent_scope}}}} end + # Whitelist the get_calls/0 (this will be expanded to a get_calls(contract.address) in postwalk) + defp prewalk( + node = {{:atom, "get_calls"}, _, []}, + acc = {:ok, %{scope: {:actions, _}}} + ) do + {node, acc} + end + # Whitelist the add_uco_transfer function parameters defp prewalk( node = {{:atom, "to"}, address}, @@ -316,6 +324,26 @@ defmodule Archethic.Contracts.ActionInterpreter do end end + # expand get_calls() to get_calls(contract.address) + defp postwalk( + {{:atom, "get_calls"}, meta, []}, + acc + ) do + node = { + {:atom, "get_calls"}, + meta, + [ + {:get_in, meta, + [ + {:scope, meta, nil}, + ["contract", "address"] + ]} + ] + } + + {node, acc} + end + defp postwalk(node, acc) do InterpreterUtils.postwalk(node, acc) end diff --git a/lib/archethic/contracts/interpreter/library.ex b/lib/archethic/contracts/interpreter/library.ex index 916a711fe..a5795636a 100644 --- a/lib/archethic/contracts/interpreter/library.ex +++ b/lib/archethic/contracts/interpreter/library.ex @@ -6,7 +6,10 @@ defmodule Archethic.Contracts.Interpreter.Library do P2P, P2P.Message.GetFirstPublicKey, P2P.Message.FirstPublicKey, - TransactionChain + TransactionChain, + Contracts.ContractConstants, + Contracts.TransactionLookup, + Contracts.Interpreter.Utils } @doc """ @@ -138,7 +141,7 @@ defmodule Archethic.Contracts.Interpreter.Library do :blake2b end - :crypto.hash(algo, decode_binary(content)) + :crypto.hash(algo, Utils.maybe_decode_hex(content)) |> Base.encode16() end @@ -177,16 +180,33 @@ defmodule Archethic.Contracts.Interpreter.Library do 2 """ @spec size(binary() | list()) :: non_neg_integer() - def size(binary) when is_binary(binary), do: binary |> decode_binary() |> byte_size() + def size(binary) when is_binary(binary), do: binary |> Utils.maybe_decode_hex() |> byte_size() def size(list) when is_list(list), do: length(list) def size(map) when is_map(map), do: map_size(map) + @doc """ + Get the inputs(type= :call) of the given transaction + + This is useful for contracts that want to throttle their calls + """ + @spec get_calls(binary()) :: list(map()) + def get_calls(contract_address) do + contract_address + |> Utils.maybe_decode_hex() + |> TransactionLookup.list_contract_transactions() + |> Enum.map(fn {address, _, _} -> + # TODO: parallelize + {:ok, tx} = TransactionChain.get_transaction(address, [], :io) + ContractConstants.from_transaction(tx) + end) + end + @doc """ Get the genesis public key """ @spec get_genesis_public_key(binary()) :: binary() def get_genesis_public_key(address) do - bin_address = decode_binary(address) + bin_address = Utils.maybe_decode_hex(address) nodes = Election.chain_storage_nodes(bin_address, P2P.authorized_and_available_nodes()) {:ok, key} = download_first_public_key(nodes, bin_address) Base.encode16(key) @@ -208,27 +228,13 @@ defmodule Archethic.Contracts.Interpreter.Library do @spec timestamp() :: non_neg_integer() def timestamp, do: DateTime.utc_now() |> DateTime.to_unix() - def decode_binary(bin) do - if String.printable?(bin) do - case Base.decode16(bin, case: :mixed) do - {:ok, hex} -> - hex - - _ -> - bin - end - else - bin - end - end - @doc """ Get the genesis address of the chain """ @spec get_genesis_address(binary()) :: binary() def get_genesis_address(address) do - addr_bin = decode_binary(address) + addr_bin = Utils.maybe_decode_hex(address) nodes = Election.chain_storage_nodes(address, P2P.authorized_and_available_nodes()) case TransactionChain.fetch_genesis_address_remotely(addr_bin, nodes) do @@ -243,7 +249,7 @@ defmodule Archethic.Contracts.Interpreter.Library do @spec get_first_transaction_address(address :: binary()) :: binary() def get_first_transaction_address(address) do - addr_bin = decode_binary(address) + addr_bin = Utils.maybe_decode_hex(address) nodes = Election.chain_storage_nodes(address, P2P.authorized_and_available_nodes()) case TransactionChain.fetch_first_transaction_address_remotely(addr_bin, nodes) do diff --git a/lib/archethic/contracts/interpreter/transaction_statements.ex b/lib/archethic/contracts/interpreter/transaction_statements.ex index 28f114b1a..d8f794c30 100644 --- a/lib/archethic/contracts/interpreter/transaction_statements.ex +++ b/lib/archethic/contracts/interpreter/transaction_statements.ex @@ -6,6 +6,8 @@ defmodule Archethic.Contracts.Interpreter.TransactionStatements do alias Archethic.TransactionChain.TransactionData.Ownership alias Archethic.TransactionChain.TransactionData.UCOLedger.Transfer, as: UCOTransfer + alias Archethic.Contracts.Interpreter.Utils + @doc """ Set the transaction type @@ -47,7 +49,7 @@ defmodule Archethic.Contracts.Interpreter.TransactionStatements do update_in( tx, [Access.key(:data), Access.key(:ledger), Access.key(:uco), Access.key(:transfers)], - &[%UCOTransfer{to: decode_binary(to), amount: amount} | &1] + &[%UCOTransfer{to: Utils.maybe_decode_hex(to), amount: amount} | &1] ) end @@ -92,9 +94,9 @@ defmodule Archethic.Contracts.Interpreter.TransactionStatements do &[ %TokenTransfer{ token_id: Map.get(map_args, "token_id", 0), - to: decode_binary(to), + to: Utils.maybe_decode_hex(to), amount: amount, - token_address: decode_binary(token_address) + token_address: Utils.maybe_decode_hex(token_address) } | &1 ] @@ -118,6 +120,14 @@ defmodule Archethic.Contracts.Interpreter.TransactionStatements do put_in(tx, [Access.key(:data), Access.key(:content)], content) end + def set_content(tx = %Transaction{}, content) when is_integer(content) do + put_in(tx, [Access.key(:data), Access.key(:content)], Integer.to_string(content)) + end + + def set_content(tx = %Transaction{}, content) when is_float(content) do + put_in(tx, [Access.key(:data), Access.key(:content)], Float.to_string(content)) + end + @doc """ Set transaction smart contract code @@ -165,9 +175,9 @@ defmodule Archethic.Contracts.Interpreter.TransactionStatements do ownership = Ownership.new( - decode_binary(secret), - decode_binary(secret_key), - Enum.map(authorized_public_keys, &decode_binary(&1)) + Utils.maybe_decode_hex(secret), + Utils.maybe_decode_hex(secret_key), + Enum.map(authorized_public_keys, &Utils.maybe_decode_hex(&1)) ) update_in( @@ -196,15 +206,7 @@ defmodule Archethic.Contracts.Interpreter.TransactionStatements do update_in( tx, [Access.key(:data), Access.key(:recipients)], - &[decode_binary(recipient_address) | &1] + &[Utils.maybe_decode_hex(recipient_address) | &1] ) end - - defp decode_binary(bin) do - if String.match?(bin, ~r/^[[:xdigit:]]+$/) do - Base.decode16!(bin, case: :mixed) - else - bin - end - end end diff --git a/lib/archethic/contracts/interpreter/utils.ex b/lib/archethic/contracts/interpreter/utils.ex index 6b54aadf1..981e9e0a2 100644 --- a/lib/archethic/contracts/interpreter/utils.ex +++ b/lib/archethic/contracts/interpreter/utils.ex @@ -340,6 +340,7 @@ defmodule Archethic.Contracts.Interpreter.Utils do def postwalk(node, acc) when is_binary(node) do if String.printable?(node) do + # uniform hexadecimal to all uppercase case Base.decode16(node, case: :mixed) do {:ok, hex} -> {Base.encode16(hex), acc} @@ -377,6 +378,21 @@ defmodule Archethic.Contracts.Interpreter.Utils do ast end + @doc """ + Decode an hexadecimal binary or no-op + """ + @spec maybe_decode_hex(binary()) :: binary() + def maybe_decode_hex(bin) do + if String.match?(bin, ~r/^[[:xdigit:]]+$/) do + case Base.decode16(bin, case: :mixed) do + {:ok, bin} -> bin + :error -> bin + end + else + bin + end + end + defp do_postwalk_execution({:=, metadata, [var_name, content]}, acc) do put_ast = {{:., metadata, [{:__aliases__, metadata, [:Map]}, :put]}, metadata, diff --git a/lib/archethic/contracts/loader.ex b/lib/archethic/contracts/loader.ex index d91946428..b0f269525 100644 --- a/lib/archethic/contracts/loader.ex +++ b/lib/archethic/contracts/loader.ex @@ -96,9 +96,6 @@ defmodule Archethic.Contracts.Loader do transaction_type: tx_type ) - # execute asynchronously the contract - Worker.execute(contract_address, tx) - TransactionLookup.add_contract_transaction( contract_address, tx_address, @@ -106,6 +103,8 @@ defmodule Archethic.Contracts.Loader do protocol_version ) + Worker.execute(contract_address, tx) + Logger.info("Transaction towards contract ingested", transaction_address: Base.encode16(tx_address), transaction_type: tx_type diff --git a/lib/archethic/db.ex b/lib/archethic/db.ex index cf2120dd1..bb6fe467e 100644 --- a/lib/archethic/db.ex +++ b/lib/archethic/db.ex @@ -16,8 +16,12 @@ defmodule Archethic.DB do @type storage_type() :: :chain | :io + @callback get_transaction(address :: binary()) :: + {:ok, Transaction.t()} | {:error, :transaction_not_exists} @callback get_transaction(address :: binary(), fields :: list()) :: {:ok, Transaction.t()} | {:error, :transaction_not_exists} + @callback get_transaction(address :: binary(), fields :: list(), storage_type :: storage_type()) :: + {:ok, Transaction.t()} | {:error, :transaction_not_exists} @callback get_beacon_summary(summary_address :: binary()) :: {:ok, Summary.t()} | {:error, :summary_not_exists} @callback get_beacon_summaries_aggregate(DateTime.t()) :: diff --git a/lib/archethic/db/embedded_impl.ex b/lib/archethic/db/embedded_impl.ex index ff905ffac..b9af3ece7 100644 --- a/lib/archethic/db/embedded_impl.ex +++ b/lib/archethic/db/embedded_impl.ex @@ -123,11 +123,23 @@ defmodule Archethic.DB.EmbeddedImpl do @doc """ Get a transaction at the given address + Read from storage first and maybe read from IO storage if flag is passed """ - @spec get_transaction(address :: binary(), fields :: list()) :: + @spec get_transaction(address :: binary(), fields :: list(), storage_type :: DB.storage_type()) :: {:ok, Transaction.t()} | {:error, :transaction_not_exists} - def get_transaction(address, fields \\ []) when is_binary(address) and is_list(fields) do - ChainReader.get_transaction(address, fields, db_path()) + def get_transaction(address, fields \\ [], storage_type \\ :chain) + when is_binary(address) and is_list(fields) do + case ChainReader.get_transaction(address, fields, db_path()) do + {:ok, transaction} -> + {:ok, transaction} + + {:error, :transaction_not_exists} -> + if storage_type == :io do + ChainReader.get_io_transaction(address, fields, db_path()) + else + {:error, :transaction_not_exists} + end + end end @doc """ diff --git a/lib/archethic/db/embedded_impl/chain_reader.ex b/lib/archethic/db/embedded_impl/chain_reader.ex index e4add6082..0d402da22 100644 --- a/lib/archethic/db/embedded_impl/chain_reader.ex +++ b/lib/archethic/db/embedded_impl/chain_reader.ex @@ -201,6 +201,21 @@ defmodule Archethic.DB.EmbeddedImpl.ChainReader do end end + @doc """ + Read a transaction from io storage + """ + @spec get_io_transaction(binary(), fields :: list(), db_path :: String.t()) :: + {:ok, Transaction.t()} | {:error, :transaction_not_exists} + def get_io_transaction(address, fields, db_path) do + filepath = ChainWriter.io_path(db_path, address) + + if File.exists?(filepath) do + {:ok, read_io_transaction(filepath, fields)} + else + {:error, :transaction_not_exists} + end + end + @doc """ List all the transactions in io storage """ diff --git a/lib/archethic/transaction_chain.ex b/lib/archethic/transaction_chain.ex index 4765ab209..6c58c88d0 100644 --- a/lib/archethic/transaction_chain.ex +++ b/lib/archethic/transaction_chain.ex @@ -142,11 +142,11 @@ defmodule Archethic.TransactionChain do {:ok, Transaction.t()} | {:error, :transaction_not_exists} | {:error, :invalid_transaction} - def get_transaction(address, fields \\ []) when is_list(fields) do + def get_transaction(address, fields \\ [], storage_type \\ :chain) when is_list(fields) do if KOLedger.has_transaction?(address) do {:error, :invalid_transaction} else - DB.get_transaction(address, fields) + DB.get_transaction(address, fields, storage_type) end end diff --git a/test/archethic/bootstrap_test.exs b/test/archethic/bootstrap_test.exs index ec320de21..27aaa22ea 100644 --- a/test/archethic/bootstrap_test.exs +++ b/test/archethic/bootstrap_test.exs @@ -563,7 +563,7 @@ defmodule Archethic.BootstrapTest do ^addr2, _ -> true ^addr1, _ -> true end) - |> expect(:get_transaction, fn ^addr3, _ -> + |> expect(:get_transaction, fn ^addr3, _, _ -> {:error, :transaction_not_exists} end) |> stub(:write_transaction, fn tx, _ -> diff --git a/test/archethic/contracts/interpreter/action_test.exs b/test/archethic/contracts/interpreter/action_test.exs index f1aaa027d..3a7d12f39 100644 --- a/test/archethic/contracts/interpreter/action_test.exs +++ b/test/archethic/contracts/interpreter/action_test.exs @@ -12,8 +12,12 @@ defmodule Archethic.Contracts.ActionInterpreterTest do alias Archethic.P2P.Message.FirstTransactionAddress alias Archethic.TransactionChain.Transaction + alias Archethic.TransactionChain.TransactionInput + alias Archethic.TransactionChain.VersionedTransactionInput alias Archethic.TransactionChain.TransactionData + alias Archethic.TransactionFactory + doctest ActionInterpreter import Mox @@ -306,6 +310,31 @@ defmodule Archethic.Contracts.ActionInterpreterTest do |> ActionInterpreter.execute() end + test "get_calls() should be expanded to get_calls(contract.address)" do + {:ok, :transaction, ast} = + ~S""" + actions triggered_by: transaction do + get_calls() + end + """ + |> Interpreter.sanitize_code() + |> elem(1) + |> ActionInterpreter.parse() + + assert {{:., [line: 2], + [ + {:__aliases__, [alias: Archethic.Contracts.Interpreter.Library], [:Library]}, + :get_calls + ]}, [line: 2], + [ + {:get_in, meta, + [ + {:scope, meta, nil}, + ["contract", "address"] + ]} + ]} = ast + end + test "shall use get_genesis_address/1 in actions" do key = <<0::16, :crypto.strong_rand_bytes(32)::binary>> @@ -437,4 +466,61 @@ defmodule Archethic.Contracts.ActionInterpreterTest do |> elem(2) |> ActionInterpreter.execute() end + + test "shall use get_calls/1 in actions" do + key = <<0::16, :crypto.strong_rand_bytes(32)::binary>> + + P2P.add_and_connect_node(%Node{ + ip: {127, 0, 0, 1}, + port: 3000, + first_public_key: key, + last_public_key: key, + available?: true, + geo_patch: "AAA", + network_patch: "AAA", + authorized?: true, + authorization_date: DateTime.utc_now() + }) + + address = Base.decode16!("64F05F5236088FC64D1BB19BD13BC548F1C49A42432AF02AD9024D8A2990B2B4") + + MockDB + |> stub(:get_inputs, fn _, ^address -> + [ + %VersionedTransactionInput{ + protocol_version: ArchethicCase.current_protocol_version(), + input: %TransactionInput{ + from: address, + amount: nil, + type: :call, + timestamp: DateTime.utc_now(), + spent?: false, + reward?: false + } + } + ] + end) + |> stub(:get_transaction, fn ^address, _, _ -> + {:ok, TransactionFactory.create_valid_transaction()} + end) + + # TODO: find a way to check the transactions returned by get_calls + + assert %Transaction{data: %TransactionData{content: "1"}} = + ~s""" + actions triggered_by: transaction do + transactions = get_calls() + set_content size(transactions) + end + """ + |> Interpreter.sanitize_code() + |> elem(1) + |> ActionInterpreter.parse() + |> elem(2) + |> ActionInterpreter.execute(%{ + "contract" => %{ + "address" => "64F05F5236088FC64D1BB19BD13BC548F1C49A42432AF02AD9024D8A2990B2B4" + } + }) + end end diff --git a/test/archethic/contracts/interpreter/library_test.exs b/test/archethic/contracts/interpreter/library_test.exs index c6cbb3a4a..072b876f5 100644 --- a/test/archethic/contracts/interpreter/library_test.exs +++ b/test/archethic/contracts/interpreter/library_test.exs @@ -25,12 +25,15 @@ defmodule Archethic.Contracts.Interpreter.LibraryTest do authorization_date: DateTime.utc_now() }) + addr1 = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::bitstring>> + addr2 = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::bitstring>> + MockClient |> expect(:send_message, fn - _, %GetFirstTransactionAddress{address: "addr2"}, _ -> - {:ok, %FirstTransactionAddress{address: "addr1"}} + _, %GetFirstTransactionAddress{address: ^addr1}, _ -> + {:ok, %FirstTransactionAddress{address: addr2}} end) - assert "addr1" == Library.get_first_transaction_address("addr2") |> Library.decode_binary() + assert Base.encode16(addr2) == Library.get_first_transaction_address(Base.encode16(addr1)) end end diff --git a/test/archethic/contracts/worker_test.exs b/test/archethic/contracts/worker_test.exs index 84cb8ea2e..7e968b909 100644 --- a/test/archethic/contracts/worker_test.exs +++ b/test/archethic/contracts/worker_test.exs @@ -442,7 +442,7 @@ defmodule Archethic.Contracts.WorkerTest do PubSub.notify_new_transaction("@Oracle1", :oracle, DateTime.utc_now()) MockDB - |> expect(:get_transaction, fn "@Oracle1", _ -> {:ok, oracle_tx} end) + |> expect(:get_transaction, fn "@Oracle1", _, _ -> {:ok, oracle_tx} end) receive do {:transaction_sent, tx} -> diff --git a/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs b/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs index fa7a33a1a..97891547e 100644 --- a/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs +++ b/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs @@ -34,7 +34,7 @@ defmodule Archethic.Crypto.SharedSecrets.SoftwareImplTest do |> expect(:list_addresses_by_type, fn :node_shared_secrets -> [:crypto.strong_rand_bytes(32)] end) - |> expect(:get_transaction, fn _, _ -> + |> expect(:get_transaction, fn _, _, _ -> {:ok, %Transaction{ data: %TransactionData{ diff --git a/test/archethic/mining/pending_transaction_validation_test.exs b/test/archethic/mining/pending_transaction_validation_test.exs index f00c19acf..8c58937f8 100644 --- a/test/archethic/mining/pending_transaction_validation_test.exs +++ b/test/archethic/mining/pending_transaction_validation_test.exs @@ -186,7 +186,7 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do assert :ok = PoolsMemTable.put_pool_member(:technical_council, tx.previous_public_key) MockDB - |> expect(:get_transaction, fn _, _ -> + |> expect(:get_transaction, fn _, _, _ -> {:ok, %Transaction{ data: %TransactionData{ @@ -350,7 +350,7 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do |> stub(:get_last_chain_address, fn address -> address end) - |> stub(:get_transaction, fn _address, [:address, :type] -> + |> stub(:get_transaction, fn _address, [:address, :type], _ -> {:error, :transaction_not_exists} end) @@ -391,7 +391,7 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do |> stub(:get_last_chain_address, fn address -> address end) - |> stub(:get_transaction, fn _address, [:address, :type] -> + |> stub(:get_transaction, fn _address, [:address, :type], _ -> {:error, :transaction_not_exists} end) @@ -429,7 +429,7 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do |> stub(:get_last_chain_address, fn address -> address end) - |> stub(:get_transaction, fn _address, [:address, :type] -> + |> stub(:get_transaction, fn _address, [:address, :type], _ -> {:error, :transaction_not_exists} end) @@ -854,7 +854,7 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do |> expect(:get_last_chain_address, fn _, _ -> {"OtherAddress", DateTime.utc_now()} end) - |> expect(:get_transaction, fn _, _ -> + |> expect(:get_transaction, fn _, _, _ -> {:ok, %Transaction{type: :node_rewards}} end) diff --git a/test/archethic/oracle_chain/scheduler_test.exs b/test/archethic/oracle_chain/scheduler_test.exs index c5b3bc865..126ced527 100644 --- a/test/archethic/oracle_chain/scheduler_test.exs +++ b/test/archethic/oracle_chain/scheduler_test.exs @@ -165,7 +165,7 @@ defmodule Archethic.OracleChain.SchedulerTest do }) MockDB - |> expect(:get_transaction, fn _, _ -> + |> expect(:get_transaction, fn _, _, _ -> {:ok, %Transaction{ type: :oracle, diff --git a/test/archethic/replication_test.exs b/test/archethic/replication_test.exs index b81f99b8e..82f5256a9 100644 --- a/test/archethic/replication_test.exs +++ b/test/archethic/replication_test.exs @@ -311,7 +311,7 @@ defmodule Archethic.ReplicationTest do MockDB |> expect(:get_genesis_address, fn _ -> "@Alice0" end) - |> expect(:get_transaction, fn _, _ -> + |> expect(:get_transaction, fn _, _, _ -> {:ok, %Transaction{ validation_stamp: %ValidationStamp{timestamp: DateTime.utc_now()}, @@ -344,7 +344,7 @@ defmodule Archethic.ReplicationTest do MockDB |> expect(:get_genesis_address, fn _ -> "@Alice0" end) - |> expect(:get_transaction, fn _, _ -> + |> expect(:get_transaction, fn _, _, _ -> {:ok, %Transaction{ validation_stamp: %ValidationStamp{timestamp: DateTime.utc_now()}, diff --git a/test/archethic/self_repair/self_repair_test.exs b/test/archethic/self_repair/self_repair_test.exs index a84d01613..4a19d04eb 100644 --- a/test/archethic/self_repair/self_repair_test.exs +++ b/test/archethic/self_repair/self_repair_test.exs @@ -39,7 +39,7 @@ defmodule Archethic.SelfRepairTest do MockDB |> expect(:get_last_chain_address, fn "Alice2" -> {"Alice2", ~U[2022-11-27 00:10:00Z]} end) - |> expect(:get_transaction, fn "Alice2", _ -> + |> expect(:get_transaction, fn "Alice2", _, _ -> {:ok, %Transaction{validation_stamp: %ValidationStamp{timestamp: ~U[2022-11-27 00:10:00Z]}}} end) |> expect(:get_genesis_address, 2, fn "Alice2" -> "Alice0" end) diff --git a/test/archethic_web/live/rewards_live_test.exs b/test/archethic_web/live/rewards_live_test.exs index e4d8bf730..3ebdd5f0b 100644 --- a/test/archethic_web/live/rewards_live_test.exs +++ b/test/archethic_web/live/rewards_live_test.exs @@ -41,7 +41,7 @@ defmodule ArchethicWeb.RewardsLiveTest do {address, time} end) end) - |> stub(:get_transaction, fn _address, [:type] -> + |> stub(:get_transaction, fn _address, [:type], _ -> {:ok, %Transaction{ type: :node_rewards diff --git a/test/support/template.ex b/test/support/template.ex index 5dded4b16..e99e2bcda 100644 --- a/test/support/template.ex +++ b/test/support/template.ex @@ -42,6 +42,7 @@ defmodule ArchethicCase do |> stub(:list_transactions, fn _ -> [] end) |> stub(:write_transaction, fn _, _ -> :ok end) |> stub(:get_transaction, fn _, _ -> {:error, :transaction_not_exists} end) + |> stub(:get_transaction, fn _, _, _ -> {:error, :transaction_not_exists} end) |> stub(:get_transaction_chain, fn _, _, _ -> {[], false, nil} end) |> stub(:list_last_transaction_addresses, fn -> [] end) |> stub(:add_last_transaction_address, fn _, _, _ -> :ok end)