From ac799af7b5040bf4240f4b22910fd225d4c18f9e Mon Sep 17 00:00:00 2001 From: neylix Date: Wed, 22 Jun 2022 10:46:32 +0200 Subject: [PATCH] Use a new transaction type --- lib/archethic/bootstrap/network_init.ex | 2 +- lib/archethic/crypto.ex | 5 +- .../keystore/shared_secrets/software_impl.ex | 5 +- lib/archethic/mining/fee.ex | 9 +--- .../mining/pending_transaction_validation.ex | 11 ++++ .../shared_secrets/mem_tables_loader.ex | 3 +- .../transaction_chain/mem_tables_loader.ex | 1 + .../transaction_chain/transaction.ex | 52 ++++++------------- .../validation_stamp/ledger_operations.ex | 21 ++++++++ .../ledger_operations/unspent_output.ex | 13 ++--- .../shared_secrets/software_impl_test.exs | 3 +- 11 files changed, 65 insertions(+), 60 deletions(-) diff --git a/lib/archethic/bootstrap/network_init.ex b/lib/archethic/bootstrap/network_init.ex index e3ca8bca49..843304a1af 100644 --- a/lib/archethic/bootstrap/network_init.ex +++ b/lib/archethic/bootstrap/network_init.ex @@ -153,7 +153,7 @@ defmodule Archethic.Bootstrap.NetworkInit do """ } - tx = %Transaction{address: address} = Transaction.new_nft_reward(data) + tx = %Transaction{address: address} = Transaction.new(:mint_rewards, data) tx |> self_validation([ diff --git a/lib/archethic/crypto.ex b/lib/archethic/crypto.ex index 22c2158a01..b542fc5f52 100755 --- a/lib/archethic/crypto.ex +++ b/lib/archethic/crypto.ex @@ -1047,13 +1047,14 @@ defmodule Archethic.Crypto do end end - def load_transaction(%Transaction{type: :node_rewards, address: address}) do + def load_transaction(%Transaction{type: type, address: address}) + when type in [:node_rewards, :mint_rewards] do nb_transactions = TransactionChain.size(address) SharedSecretsKeystore.set_network_pool_key_index(nb_transactions) Logger.info("Network pool chain positioned at#{nb_transactions}", transaction_address: Base.encode16(address), - transaction_type: :node_rewards + transaction_type: type ) end diff --git a/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex b/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex index a889ccbf53..8cc65a49bd 100644 --- a/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex +++ b/lib/archethic/crypto/keystore/shared_secrets/software_impl.ex @@ -39,7 +39,10 @@ defmodule Archethic.Crypto.SharedSecretsKeystore.SoftwareImpl do Logger.info("Node shared secrets keys positioned at #{nb_node_shared_secrets_keys}") - nb_network_pool_keys = TransactionChain.count_transactions_by_type(:node_rewards) + nb_network_pool_keys = + TransactionChain.count_transactions_by_type(:node_rewards) + + TransactionChain.count_transactions_by_type(:mint_rewards) + Logger.info("Network pool keys positioned at #{nb_network_pool_keys}") :ets.insert(@keystore_table, {:shared_secrets_index, nb_node_shared_secrets_keys}) diff --git a/lib/archethic/mining/fee.ex b/lib/archethic/mining/fee.ex index 54ff318a3b..ae6e3dc447 100644 --- a/lib/archethic/mining/fee.ex +++ b/lib/archethic/mining/fee.ex @@ -7,9 +7,7 @@ defmodule Archethic.Mining.Fee do alias Archethic.Election alias Archethic.P2P - alias Archethic.Crypto - alias Archethic.TransactionChain alias Archethic.TransactionChain.Transaction alias Archethic.TransactionChain.TransactionData alias Archethic.TransactionChain.TransactionData.Ledger @@ -32,8 +30,7 @@ defmodule Archethic.Mining.Fee do def calculate( tx = %Transaction{ address: address, - type: type, - previous_public_key: previous_public_key + type: type }, uco_price_in_usd ) do @@ -41,10 +38,6 @@ defmodule Archethic.Mining.Fee do address == Bootstrap.genesis_address() -> 0 - TransactionChain.get_first_public_key(previous_public_key) == - Crypto.network_pool_public_key(0) -> - 0 - true == Transaction.network_type?(type) -> 0 diff --git a/lib/archethic/mining/pending_transaction_validation.ex b/lib/archethic/mining/pending_transaction_validation.ex index 383861bcc4..a4460904de 100644 --- a/lib/archethic/mining/pending_transaction_validation.ex +++ b/lib/archethic/mining/pending_transaction_validation.ex @@ -117,6 +117,17 @@ defmodule Archethic.Mining.PendingTransactionValidation do end end + defp do_accept_transaction(%Transaction{ + type: :mint_rewards, + data: %TransactionData{content: content} + }) do + if Regex.match?(~r/(?<=initial supply:).*\d/mi, content) do + :ok + else + {:error, "Invalid mint rewards content"} + end + end + defp do_accept_transaction(%Transaction{ type: :node, data: %TransactionData{ diff --git a/lib/archethic/shared_secrets/mem_tables_loader.ex b/lib/archethic/shared_secrets/mem_tables_loader.ex index aa23501abc..6f7da6c0c1 100644 --- a/lib/archethic/shared_secrets/mem_tables_loader.ex +++ b/lib/archethic/shared_secrets/mem_tables_loader.ex @@ -138,7 +138,8 @@ defmodule Archethic.SharedSecrets.MemTablesLoader do ) end - def load_transaction(%Transaction{type: :node_rewards, address: address}) do + def load_transaction(%Transaction{type: type, address: address}) + when type in [:node_rewards, :mint_rewards] do NetworkLookup.set_network_pool_address(address) end diff --git a/lib/archethic/transaction_chain/mem_tables_loader.ex b/lib/archethic/transaction_chain/mem_tables_loader.ex index efddab0deb..9fe85a689e 100644 --- a/lib/archethic/transaction_chain/mem_tables_loader.ex +++ b/lib/archethic/transaction_chain/mem_tables_loader.ex @@ -29,6 +29,7 @@ defmodule Archethic.TransactionChain.MemTablesLoader do :beacon, :beacon_summary, :node_rewards, + :mint_rewards, :origin ] diff --git a/lib/archethic/transaction_chain/transaction.ex b/lib/archethic/transaction_chain/transaction.ex index d11f576916..9c12aa8db2 100755 --- a/lib/archethic/transaction_chain/transaction.ex +++ b/lib/archethic/transaction_chain/transaction.ex @@ -63,6 +63,7 @@ defmodule Archethic.TransactionChain.Transaction do :node | :node_shared_secrets | :node_rewards + | :mint_rewards | :beacon | :beacon_summary | :oracle @@ -84,6 +85,7 @@ defmodule Archethic.TransactionChain.Transaction do :oracle, :oracle_summary, :node_rewards, + :mint_rewards, :code_proposal, :code_approval, :keychain, @@ -121,24 +123,6 @@ defmodule Archethic.TransactionChain.Transaction do |> origin_sign_transaction() end - @doc """ - Create a new pending transaction using the Crypto keystore to find out - the seed and the transaction index for the nft reward minting - """ - @spec new_nft_reward(data :: TransactionData.t()) :: t() - def new_nft_reward(data = %TransactionData{}) do - {previous_public_key, next_public_key} = get_network_public_key() - - %__MODULE__{ - address: Crypto.derive_address(next_public_key), - type: :nft, - data: data, - previous_public_key: previous_public_key - } - |> previous_network_sign_transaction() - |> origin_sign_transaction() - end - @doc """ Create a new pending transaction @@ -199,8 +183,11 @@ defmodule Archethic.TransactionChain.Transaction do {previous_public_key, next_public_key} end - defp get_transaction_public_keys(:node_rewards) do - get_network_public_key() + defp get_transaction_public_keys(type) when type in [:node_rewards, :mint_rewards] do + key_index = Crypto.number_of_network_pool_keys() + previous_public_key = Crypto.network_pool_public_key(key_index) + next_public_key = Crypto.network_pool_public_key(key_index + 1) + {previous_public_key, next_public_key} end defp get_transaction_public_keys(_) do @@ -209,13 +196,6 @@ defmodule Archethic.TransactionChain.Transaction do {previous_public_key, next_public_key} end - defp get_network_public_key() do - key_index = Crypto.number_of_network_pool_keys() - previous_public_key = Crypto.network_pool_public_key(key_index) - next_public_key = Crypto.network_pool_public_key(key_index + 1) - {previous_public_key, next_public_key} - end - defp previous_sign_transaction(tx = %__MODULE__{type: :node_shared_secrets}) do key_index = Crypto.number_of_node_shared_secrets_keys() @@ -228,28 +208,25 @@ defmodule Archethic.TransactionChain.Transaction do %{tx | previous_signature: previous_signature} end - defp previous_sign_transaction(tx = %__MODULE__{type: :node_rewards}) do - previous_network_sign_transaction(tx) - end + defp previous_sign_transaction(tx = %__MODULE__{type: type}) + when type in [:node_rewards, :mint_rewards] do + key_index = Crypto.number_of_network_pool_keys() - defp previous_sign_transaction(tx = %__MODULE__{}) do previous_signature = tx |> extract_for_previous_signature() |> serialize() - |> Crypto.sign_with_previous_node_key() + |> Crypto.sign_with_network_pool_key(key_index) %{tx | previous_signature: previous_signature} end - defp previous_network_sign_transaction(tx = %__MODULE__{}) do - key_index = Crypto.number_of_network_pool_keys() - + defp previous_sign_transaction(tx = %__MODULE__{}) do previous_signature = tx |> extract_for_previous_signature() |> serialize() - |> Crypto.sign_with_network_pool_key(key_index) + |> Crypto.sign_with_previous_node_key() %{tx | previous_signature: previous_signature} end @@ -334,6 +311,7 @@ defmodule Archethic.TransactionChain.Transaction do def serialize_type(:code_proposal), do: 7 def serialize_type(:code_approval), do: 8 def serialize_type(:node_rewards), do: 9 + def serialize_type(:mint_rewards), do: 10 # User transaction's type def serialize_type(:keychain), do: 255 @@ -357,6 +335,7 @@ defmodule Archethic.TransactionChain.Transaction do def parse_type(7), do: :code_proposal def parse_type(8), do: :code_approval def parse_type(9), do: :node_rewards + def parse_type(10), do: :mint_rewards # User transaction's type def parse_type(255), do: :keychain @@ -377,6 +356,7 @@ defmodule Archethic.TransactionChain.Transaction do def network_type?(:oracle), do: true def network_type?(:oracle_summary), do: true def network_type?(:node_rewards), do: true + def network_type?(:mint_rewards), do: true def network_type?(_), do: false @doc """ diff --git a/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations.ex b/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations.ex index f09345530b..89f133c67d 100644 --- a/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations.ex +++ b/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations.ex @@ -80,6 +80,27 @@ defmodule Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperation } end + def from_transaction(ops = %__MODULE__{}, %Transaction{ + address: address, + type: :mint_rewards, + data: %TransactionData{content: content} + }) do + [[match | _]] = Regex.scan(~r/(?<=initial supply:).*\d/mi, content) + + {initial_supply, _} = + match + |> String.trim() + |> String.replace(" ", "") + |> Integer.parse() + + %{ + ops + | unspent_outputs: [ + %UnspentOutput{from: address, amount: initial_supply * @unit_uco, type: {:NFT, address}} + ] + } + end + def from_transaction(ops = %__MODULE__{}, %Transaction{}), do: ops @doc """ diff --git a/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations/unspent_output.ex b/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations/unspent_output.ex index a5acd79feb..23ec52eef4 100644 --- a/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations/unspent_output.ex +++ b/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations/unspent_output.ex @@ -122,18 +122,11 @@ defmodule Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperation @spec from_map(map()) :: __MODULE__.t() def from_map(unspent_output = %{}) do - res = %__MODULE__{ + %__MODULE__{ from: Map.get(unspent_output, :from), - amount: Map.get(unspent_output, :amount) + amount: Map.get(unspent_output, :amount), + type: Map.get(unspent_output, :type) } - - case Map.get(unspent_output, :type) do - "NFT" -> - %{res | type: {:NFT, Map.get(unspent_output, :nft_address)}} - - _ -> - %{res | type: :UCO} - end end @spec to_map(t()) :: map() 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 6242d7e77e..fbed8e7617 100644 --- a/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs +++ b/test/archethic/crypto/keystore/shared_secrets/software_impl_test.exs @@ -29,6 +29,7 @@ defmodule Archethic.Crypto.SharedSecrets.SoftwareImplTest do |> stub(:count_transactions_by_type, fn :node_rewards -> 1 :node_shared_secrets -> 1 + :mint_rewards -> 1 end) |> expect(:list_addresses_by_type, fn :node_shared_secrets -> [:crypto.strong_rand_bytes(32)] @@ -52,7 +53,7 @@ defmodule Archethic.Crypto.SharedSecrets.SoftwareImplTest do unix_timestamp = DateTime.to_unix(timestamp) assert [{_, 1}] = :ets.lookup(:archethic_shared_secrets_keystore, :shared_secrets_index) - assert [{_, 1}] = :ets.lookup(:archethic_shared_secrets_keystore, :network_pool_index) + assert [{_, 2}] = :ets.lookup(:archethic_shared_secrets_keystore, :network_pool_index) assert [{^unix_timestamp, ^daily_nonce_keypair}] = :ets.tab2list(:archethic_shared_secrets_daily_keys)