From f1bb2bc2eb5a88f6bdf6aacc286580a2ea5d5d62 Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 26 Aug 2022 17:14:14 +0200 Subject: [PATCH] Fix last network address in verification tx --- .../mining/pending_transaction_validation.ex | 14 +- .../pending_transaction_validation_test.exs | 344 ++++++++++++++++++ 2 files changed, 352 insertions(+), 6 deletions(-) diff --git a/lib/archethic/mining/pending_transaction_validation.ex b/lib/archethic/mining/pending_transaction_validation.ex index e3499233f6..756e640543 100644 --- a/lib/archethic/mining/pending_transaction_validation.ex +++ b/lib/archethic/mining/pending_transaction_validation.ex @@ -224,15 +224,16 @@ defmodule Archethic.Mining.PendingTransactionValidation do ) do last_scheduling_date = Reward.get_last_scheduling_date(validation_time) - network_pool_address = SharedSecrets.get_network_pool_address() + genesis_address = DB.list_addresses_by_type(:mint_rewards) |> Stream.take(1) |> Enum.at(0) + {last_network_pool_address, _} = DB.get_last_chain_address(genesis_address) previous_address = Transaction.previous_address(tx) time_validation = with {:ok, %Transaction{type: :node_rewards}} <- TransactionChain.get_transaction(previous_address, [:type]), - {^network_pool_address, _} <- - DB.get_last_chain_address(network_pool_address, last_scheduling_date) do + {^last_network_pool_address, _} <- + DB.get_last_chain_address(genesis_address, last_scheduling_date) do :ok else {:ok, %Transaction{type: :mint_rewards}} -> @@ -505,12 +506,13 @@ defmodule Archethic.Mining.PendingTransactionValidation do _ ) do total_fee = DB.get_latest_burned_fees() + genesis_address = DB.list_addresses_by_type(:mint_rewards) |> Stream.take(1) |> Enum.at(0) + {last_address, _} = DB.get_last_chain_address(genesis_address) with :ok <- verify_token_creation(content), {:ok, %{"supply" => ^total_fee}} <- Jason.decode(content), - network_pool_address <- SharedSecrets.get_network_pool_address(), - {^network_pool_address, _} <- - DB.get_last_chain_address(network_pool_address, Reward.last_scheduling_date()) do + {^last_address, _} <- + DB.get_last_chain_address(genesis_address, Reward.last_scheduling_date()) do :ok else {:ok, %{"supply" => _}} -> diff --git a/test/archethic/mining/pending_transaction_validation_test.exs b/test/archethic/mining/pending_transaction_validation_test.exs index 2bbea70db4..d006e31a10 100644 --- a/test/archethic/mining/pending_transaction_validation_test.exs +++ b/test/archethic/mining/pending_transaction_validation_test.exs @@ -203,6 +203,350 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do assert :ok = PendingTransactionValidation.validate(tx) :persistent_term.put(:node_shared_secrets_gen_addr, nil) end + + test "should return :ok when a origin transaction is made" do + P2P.add_and_connect_node(%Node{ + ip: {127, 0, 0, 1}, + port: 3000, + http_port: 4000, + first_public_key: "node_key1", + last_public_key: "node_key1", + available?: true + }) + + P2P.add_and_connect_node(%Node{ + ip: {127, 0, 0, 1}, + port: 3000, + http_port: 4000, + first_public_key: "node_key2", + last_public_key: "node_key2", + available?: true + }) + + {public_key, _} = Crypto.derive_keypair("random", 0) + certificate = Crypto.get_key_certificate(public_key) + certificate_size = byte_size(certificate) + + tx = + Transaction.new( + :origin, + %TransactionData{ + code: """ + condition inherit: [ + type: origin, + content: true + ] + """, + content: <> + } + ) + + assert :ok = PendingTransactionValidation.validate(tx) + end + + test "should return :ok when a code approval transaction contains a proposal target and the sender is member of the technical council and not previously signed" do + tx = + Transaction.new( + :code_approval, + %TransactionData{ + recipients: ["@CodeProposal1"] + }, + "approval_seed", + 0 + ) + + P2P.add_and_connect_node(%Node{ + ip: {127, 0, 0, 1}, + port: 3000, + http_port: 4000, + first_public_key: "node1", + last_public_key: "node1", + geo_patch: "AAA", + network_patch: "AAA", + available?: true, + authorized?: true, + authorization_date: DateTime.utc_now() + }) + + assert :ok = PoolsMemTable.put_pool_member(:technical_council, tx.previous_public_key) + + MockDB + |> expect(:get_transaction, fn _, _ -> + {:ok, + %Transaction{ + data: %TransactionData{ + content: """ + Description: My Super Description + Changes: + diff --git a/mix.exs b/mix.exs + index d9d9a06..5e34b89 100644 + --- a/mix.exs + +++ b/mix.exs + @@ -4,7 +4,7 @@ defmodule Archethic.MixProject do + def project do + [ + app: :archethic, + - version: \"0.7.1\", + + version: \"0.7.2\", + build_path: \"_build\", + config_path: \"config/config.exs\", + deps_path: \"deps\", + @@ -53,7 +53,7 @@ defmodule Archethic.MixProject do + {:git_hooks, \"~> 0.4.0\", only: [:test, :dev], runtime: false}, + {:mox, \"~> 0.5.2\", only: [:test]}, + {:stream_data, \"~> 0.4.3\", only: [:test]}, + - {:elixir_make, \"~> 0.6.0\", only: [:dev, :test], runtime: false}, + + {:elixir_make, \"~> 0.6.0\", only: [:dev, :test]}, + {:logger_file_backend, \"~> 0.0.11\", only: [:dev]} + ] + end + """ + } + }} + end) + + MockClient + |> expect(:send_message, fn _, %GetFirstPublicKey{}, _ -> + {:ok, %FirstPublicKey{public_key: tx.previous_public_key}} + end) + + assert :ok = PendingTransactionValidation.validate(tx) + end + + test "should return :ok when a transaction contains a valid smart contract code" do + tx_seed = :crypto.strong_rand_bytes(32) + + tx = + Transaction.new( + :transfer, + %TransactionData{ + code: """ + condition inherit: [ + content: "hello" + ] + + condition transaction: [ + content: "" + ] + + actions triggered_by: transaction do + set_content "hello" + end + """, + ownerships: [ + Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [ + Crypto.storage_nonce_public_key() + ]) + ] + }, + tx_seed, + 0 + ) + + assert :ok = PendingTransactionValidation.validate(tx) + end + + test "should return :ok when a transaction contains valid fields for token creation" do + tx_seed = :crypto.strong_rand_bytes(32) + + tx = + Transaction.new( + :token, + %TransactionData{ + content: + Jason.encode!(%{ + supply: 300_000_000, + name: "MyToken", + type: "non-fungible", + symbol: "MTK", + properties: [ + [ + %{name: "image", value: "link"} + ], + [ + %{name: "image", value: "link"} + ], + [ + %{name: "image", value: "link"} + ] + ] + }) + }, + tx_seed, + 0 + ) + + assert :ok = PendingTransactionValidation.validate(tx) + end + + test "should return :ok when a mint reward transaction passes all tests" do + tx_seed = :crypto.strong_rand_bytes(32) + {pub, _} = Crypto.derive_keypair(tx_seed, 1) + address = Crypto.derive_address(pub) + + NetworkLookup.set_network_pool_address(address) + + Scheduler.start_link(interval: "0 * * * * *") + + MockDB + |> stub(:get_latest_burned_fees, fn -> 300_000_000 end) + |> stub(:get_last_chain_address, fn _, _ -> {address, DateTime.utc_now()} end) + |> stub(:get_last_chain_address, fn _ -> {address, DateTime.utc_now()} end) + + tx = + Transaction.new( + :mint_rewards, + %TransactionData{ + content: + Jason.encode!(%{ + supply: 300_000_000, + name: "MyToken", + type: "fungible", + symbol: "MTK", + properties: [ + [ + %{name: "image", value: "link"} + ], + [ + %{name: "image", value: "link"} + ], + [ + %{name: "image", value: "link"} + ] + ] + }) + }, + tx_seed, + 0 + ) + + assert :ok = PendingTransactionValidation.validate(tx) + end + + test "should return :error when a mint reward transaction has != burned_fees" do + tx_seed = :crypto.strong_rand_bytes(32) + {pub, _} = Crypto.derive_keypair(tx_seed, 1) + address = Crypto.derive_address(pub) + + NetworkLookup.set_network_pool_address(address) + + Scheduler.start_link(interval: "0 * * * * *") + + MockDB + |> stub(:get_latest_burned_fees, fn -> 200_000_000 end) + |> stub(:get_last_chain_address, fn _, _ -> address end) + + tx = + Transaction.new( + :mint_rewards, + %TransactionData{ + content: + Jason.encode!(%{ + supply: 300_000_000, + name: "MyToken", + type: "fungible", + symbol: "MTK" + }) + }, + tx_seed, + 0 + ) + + assert {:error, "The supply do not match burned fees from last summary"} = + PendingTransactionValidation.validate(tx) + end + + test "should return :error when there is already a mint rewards transaction since last schedule" do + tx_seed = :crypto.strong_rand_bytes(32) + {pub, _} = Crypto.derive_keypair(tx_seed, 1) + address = Crypto.derive_address(pub) + + NetworkLookup.set_network_pool_address(:crypto.strong_rand_bytes(32)) + + Scheduler.start_link(interval: "0 * * * * *") + + MockDB + |> stub(:get_latest_burned_fees, fn -> 300_000_000 end) + |> stub(:get_last_chain_address, fn _, _ -> {address, DateTime.utc_now()} end) + + tx = + Transaction.new( + :mint_rewards, + %TransactionData{ + content: + Jason.encode!(%{ + supply: 300_000_000, + name: "MyToken", + type: "fungible", + symbol: "MTK" + }) + }, + tx_seed, + 0 + ) + + assert {:error, "There is already a mint rewards transaction since last schedule"} = + PendingTransactionValidation.validate(tx) + end + + test "should return error when there is already a oracle transaction since the last schedule" do + MockDB + |> expect(:get_last_chain_address, fn _, _ -> + {"OtherAddress", DateTime.utc_now()} + end) + + tx = Transaction.new(:oracle, %TransactionData{}, "seed", 0) + + assert {:error, "Invalid oracle trigger time"} = + PendingTransactionValidation.validate(tx, ~U[2022-01-01 00:10:03Z]) + end + + test "should return error when there is already a node shared secrets transaction since the last schedule" do + MockDB + |> expect(:get_last_chain_address, fn _, _ -> + {"OtherAddress", DateTime.utc_now()} + end) + + tx = + Transaction.new( + :node_shared_secrets, + %TransactionData{ + content: :crypto.strong_rand_bytes(32), + ownerships: [ + %Ownership{ + secret: :crypto.strong_rand_bytes(32), + authorized_keys: %{"node_key" => :crypto.strong_rand_bytes(32)} + } + ] + }, + "seed", + 0 + ) + + assert {:error, "Invalid node shared secrets trigger time"} = + PendingTransactionValidation.validate(tx, ~U[2022-01-01 00:00:03Z]) + end + + test "should return error when there is already a node rewards transaction since the last schedule" do + MockDB + |> expect(:get_last_chain_address, fn _, _ -> + {"OtherAddress", DateTime.utc_now()} + end) + |> expect(:get_transaction, fn _, _ -> + {:ok, %Transaction{type: :node_rewards}} + end) + + tx = + Transaction.new( + :node_rewards, + %TransactionData{}, + "seed", + 0 + ) + + assert {:error, "Invalid node rewards trigger time"} = + PendingTransactionValidation.validate(tx, ~U[2022-01-01 00:00:03Z]) + end end test "should return :ok when a origin transaction is made" do