diff --git a/lib/archethic/beacon_chain/summary.ex b/lib/archethic/beacon_chain/summary.ex index 049adc2db..2817eee3b 100644 --- a/lib/archethic/beacon_chain/summary.ex +++ b/lib/archethic/beacon_chain/summary.ex @@ -307,12 +307,12 @@ defmodule Archethic.BeaconChain.Summary do # Then do a wheighted mean of the result map = availabilities - |> Map.values() - |> Enum.map(&Utils.median(&1)) + |> Enum.sort_by(fn {slot_time, _} -> slot_time end, {:asc, DateTime}) + |> Enum.map(fn {_, availabilities} -> Utils.median(availabilities) end) |> Enum.with_index() |> Enum.reduce(%{}, fn {slot_availability_time, slot_index}, acc -> # 1,0 -> 1,1 -> 1,2 ... - # Weight for 144th slot = 15.4 + # Weight for 144th slot = 15.3 weight = 1 + slot_index / 10 weighted_availability_time = slot_availability_time * weight diff --git a/lib/archethic/replication/transaction_context.ex b/lib/archethic/replication/transaction_context.ex index e6714a1fd..958ae313c 100644 --- a/lib/archethic/replication/transaction_context.ex +++ b/lib/archethic/replication/transaction_context.ex @@ -23,7 +23,7 @@ defmodule Archethic.Replication.TransactionContext do {:ok, tx} -> tx - {:error, :transaction_not_exists} -> + {:error, _} -> nil end end diff --git a/lib/archethic/transaction_chain.ex b/lib/archethic/transaction_chain.ex index 1d9176768..81ad9dee7 100644 --- a/lib/archethic/transaction_chain.ex +++ b/lib/archethic/transaction_chain.ex @@ -210,7 +210,7 @@ defmodule Archethic.TransactionChain do } = Enum.at(sorted_chain, 0) DB.write_transaction_chain(sorted_chain) - KOLedger.remove_transaction(tx_address) + Enum.each(sorted_chain, &KOLedger.remove_transaction(&1.address)) Logger.info("Transaction Chain stored", transaction_address: Base.encode16(tx_address), @@ -793,16 +793,39 @@ defmodule Archethic.TransactionChain do end defp do_fetch_transaction_chain(nodes, address, paging_state, opts \\ []) do + order = Keyword.get(opts, :order, :asc) + conflict_resolver = fn results -> results |> Enum.sort( - &((&1.more? and !&2.more?) or length(&1.transactions) > length(&2.transactions)) + # Prioritize more? at true + # then length of transaction list + # then regarding order, the oldest or newest transaction timestamp + # of the first element of the list + &with false <- &1.more? and !&2.more?, + false <- length(&1.transactions) > length(&2.transactions) do + if Enum.empty?(&1.transactions) do + false + else + case order do + :asc -> + DateTime.compare( + List.first(&1.transactions).validation_stamp.timestamp, + List.first(&2.transactions).validation_stamp.timestamp + ) == :lt + + :desc -> + DateTime.compare( + List.first(&1.transactions).validation_stamp.timestamp, + List.first(&2.transactions).validation_stamp.timestamp + ) == :gt + end + end + end ) |> List.first() end - order = Keyword.get(opts, :order, :asc) - # We got transactions by batch of 10 transactions timeout = Message.get_max_timeout() + Message.get_max_timeout() * 10 diff --git a/lib/archethic_web/controllers/api/schema/ownership.ex b/lib/archethic_web/controllers/api/schema/ownership.ex index bc2fe606c..02b312a26 100644 --- a/lib/archethic_web/controllers/api/schema/ownership.ex +++ b/lib/archethic_web/controllers/api/schema/ownership.ex @@ -21,29 +21,5 @@ defmodule ArchethicWeb.API.Schema.Ownership do max: 256, message: "maximum number of authorized keys can be 256" ) - |> format_authorized_keys() end - - defp format_authorized_keys( - changeset = %Ecto.Changeset{valid?: true, changes: %{authorizedKeys: authorized_keys}} - ) do - new_authorized_keys_changesets = - Enum.reduce(authorized_keys, %{}, fn %Ecto.Changeset{ - changes: %{ - publicKey: public_key, - encryptedSecretKey: encrypted_secret_key - } - }, - acc -> - Map.put(acc, public_key, encrypted_secret_key) - end) - - put_in( - changeset, - [Access.key(:changes, %{}), Access.key(:authorizedKeys, %{})], - new_authorized_keys_changesets - ) - end - - defp format_authorized_keys(changeset), do: changeset end diff --git a/lib/archethic_web/controllers/api/transaction_payload.ex b/lib/archethic_web/controllers/api/transaction_payload.ex index 95c0a8e9c..a939b7f14 100644 --- a/lib/archethic_web/controllers/api/transaction_payload.ex +++ b/lib/archethic_web/controllers/api/transaction_payload.ex @@ -49,6 +49,8 @@ defmodule ArchethicWeb.API.TransactionPayload do def to_map(%{changes: changes}, acc) do Enum.reduce(changes, acc, fn {key, value}, acc -> + value = format_change(key, value) + key = Macro.underscore(Atom.to_string(key)) case value do @@ -67,6 +69,20 @@ defmodule ArchethicWeb.API.TransactionPayload do def to_map(value, _), do: value + defp format_change(:authorizedKeys, authorized_keys) do + Enum.reduce(authorized_keys, %{}, fn %Ecto.Changeset{ + changes: %{ + publicKey: public_key, + encryptedSecretKey: encrypted_secret_key + } + }, + acc -> + Map.put(acc, public_key, encrypted_secret_key) + end) + end + + defp format_change(_, value), do: value + defp validate_data(changeset = %Ecto.Changeset{}) do validate_change(changeset, :data, fn _, data_changeset -> case data_changeset.valid? do diff --git a/mix.lock b/mix.lock index df7cf609a..8383f0135 100644 --- a/mix.lock +++ b/mix.lock @@ -23,8 +23,8 @@ "earmark": {:hex, :earmark, "1.4.34", "d7f89d3bbd7567a0bffc465e0a949f8f8dcbe43909c3acf96f4761a302cea10c", [:mix], [{:earmark_parser, "~> 1.4.29", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "90b106f3dad85b133b10d7d628167c88246123fd1cecb4557d83d21ec9e65504"}, "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, "easy_ssl": {:hex, :easy_ssl, "1.3.0", "472256942d9dd37652a558a789a8d1cccc27e7f46352e32667d1ca46bb9e22e5", [:mix], [], "hexpm", "ce8fcb7661442713a94853282b56cee0b90c52b983a83aa6af24686d301808e1"}, - "ecto": {:hex, :ecto, "3.9.2", "017db3bc786ff64271108522c01a5d3f6ba0aea5c84912cfb0dd73bf13684108", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "21466d5177e09e55289ac7eade579a642578242c7a3a9f91ad5c6583337a9d15"}, - "elixir_make": {:hex, :elixir_make, "0.7.2", "e83548b0500e654d1a595f1134af4862a2e92ec3282ec4c2a17641e9aa45ee73", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "05fb44abf9582381c2eb1b73d485a55288c581071de0ee3ee1084ee69d6a8e5f"}, + "ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"}, + "elixir_make": {:hex, :elixir_make, "0.7.3", "c37fdae1b52d2cc51069713a58c2314877c1ad40800a57efb213f77b078a460d", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "24ada3e3996adbed1fa024ca14995ef2ba3d0d17b678b0f3f2b1f66e6ce2b274"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "esbuild": {:hex, :esbuild, "0.6.0", "9ba6ead054abd43cb3d7b14946a0cdd1493698ccd8e054e0e5d6286d7f0f509c", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "30f9a05d4a5bab0d3e37398f312f80864e1ee1a081ca09149d06d474318fd040"}, "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, @@ -32,7 +32,7 @@ "exjsonpath": {:hex, :exjsonpath, "0.9.0", "87e593eb0deb53aa0688ca9f9edc9fb3456aca83c82245f83201ea04d696feba", [:mix], [], "hexpm", "8d7a8e9ba784e1f7a67c6f1074a3ac91a3a79a45969514ee5d95cea5bf749627"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "floki": {:hex, :floki, "0.34.0", "002d0cc194b48794d74711731db004fafeb328fe676976f160685262d43706a8", [:mix], [], "hexpm", "9c3a9f43f40dde00332a589bd9d389b90c1f518aef500364d00636acc5ebc99c"}, - "flow": {:hex, :flow, "1.2.0", "515e03aa3d056cecc3e3f1e80f6ca4bbf5f45b13c88dee5db880b2f3f24f1caa", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "1b45bfc8a9202c5ec80b077c21df133561e56c56189ba4082dddccb6b5762525"}, + "flow": {:hex, :flow, "1.2.1", "cfe984b2078ced0bc92807737909abe1b158288256244cc77d03ad96cbef1571", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "3f9fe6a4b28b8e82822d7a851c8d8fe3ac3c0e597aa2cf3cccd81f9af561abee"}, "gen_stage": {:hex, :gen_stage, "1.1.2", "b1656cd4ba431ed02c5656fe10cb5423820847113a07218da68eae5d6a260c23", [:mix], [], "hexpm", "9e39af23140f704e2b07a3e29d8f05fd21c2aaf4088ff43cb82be4b9e3148d02"}, "gen_state_machine": {:hex, :gen_state_machine, "3.0.0", "1e57f86a494e5c6b14137ebef26a7eb342b3b0070c7135f2d6768ed3f6b6cdff", [:mix], [], "hexpm", "0a59652574bebceb7309f6b749d2a41b45fdeda8dbb4da0791e355dd19f0ed15"}, "git_hooks": {:hex, :git_hooks, "0.7.3", "09489e94d88dfc767662e22aff2b6208bd7cf555a19dd0e1477cca4683ce0701", [:mix], [{:blankable, "~> 1.0.0", [hex: :blankable, repo: "hexpm", optional: false]}, {:recase, "~> 0.7.0", [hex: :recase, repo: "hexpm", optional: false]}], "hexpm", "d6ddedeb4d3a8602bc3f84e087a38f6150a86d9e790628ed8bc70e6d90681659"}, @@ -66,7 +66,7 @@ "ranch": {:hex, :ranch, "2.1.0", "2261f9ed9574dcfcc444106b9f6da155e6e540b2f82ba3d42b339b93673b72a3", [:make, :rebar3], [], "hexpm", "244ee3fa2a6175270d8e1fc59024fd9dbc76294a321057de8f803b1479e76916"}, "rand_compat": {:hex, :rand_compat, "0.0.3", "011646bc1f0b0c432fe101b816f25b9bbb74a085713cee1dafd2d62e9415ead3", [:rebar3], [], "hexpm", "cdf7be2b17308ec245b912c45fe55741f93b6e4f1a24ba6074f7137b0cc09bf4"}, "recase": {:hex, :recase, "0.7.0", "3f2f719f0886c7a3b7fe469058ec539cb7bbe0023604ae3bce920e186305e5ae", [:mix], [], "hexpm", "36f5756a9f552f4a94b54a695870e32f4e72d5fad9c25e61bc4a3151c08a4e0c"}, - "recon": {:hex, :recon, "2.5.2", "cba53fa8db83ad968c9a652e09c3ed7ddcc4da434f27c3eaa9ca47ffb2b1ff03", [:mix, :rebar3], [], "hexpm", "2c7523c8dee91dff41f6b3d63cba2bd49eb6d2fe5bf1eec0df7f87eb5e230e1c"}, + "recon": {:hex, :recon, "2.5.3", "739107b9050ea683c30e96de050bc59248fd27ec147696f79a8797ff9fa17153", [:mix, :rebar3], [], "hexpm", "6c6683f46fd4a1dfd98404b9f78dcabc7fcd8826613a89dcb984727a8c3099d7"}, "retry": {:hex, :retry, "0.17.0", "2582b6371155b6c1abdb95e5d35e82c0a3947be61ae8eb72085f1582ef47b652", [:mix], [], "hexpm", "27ab3fd96fc58c05b0a411abb6d150de8b6fe97a8327519171597498a6694024"}, "sizeable": {:hex, :sizeable, "1.0.2", "625fe06a5dad188b52121a140286f1a6ae1adf350a942cf419499ecd8a11ee29", [:mix], [], "hexpm", "4bab548e6dfba777b400ca50830a9e3a4128e73df77ab1582540cf5860601762"}, "sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"}, diff --git a/test/archethic/transaction_chain_test.exs b/test/archethic/transaction_chain_test.exs index 18babf49b..2f89a310e 100644 --- a/test/archethic/transaction_chain_test.exs +++ b/test/archethic/transaction_chain_test.exs @@ -275,6 +275,8 @@ defmodule Archethic.TransactionChainTest do Enum.each(nodes, &P2P.add_and_connect_node/1) + validation_stamp = %ValidationStamp{timestamp: DateTime.utc_now()} + MockClient |> stub(:send_message, fn %Node{port: 3000}, %GetTransactionChain{address: _}, _ -> @@ -284,10 +286,10 @@ defmodule Archethic.TransactionChainTest do {:ok, %TransactionList{ transactions: [ - %Transaction{}, - %Transaction{}, - %Transaction{}, - %Transaction{} + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp} ], more?: false }} @@ -296,11 +298,11 @@ defmodule Archethic.TransactionChainTest do {:ok, %TransactionList{ transactions: [ - %Transaction{}, - %Transaction{}, - %Transaction{}, - %Transaction{}, - %Transaction{} + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp}, + %Transaction{validation_stamp: validation_stamp} ], more?: false }}