From b850451f2609503089abc1ebd35c3c7eb56a4d21 Mon Sep 17 00:00:00 2001 From: Samuel Date: Mon, 2 May 2022 22:05:45 +0200 Subject: [PATCH] Fix ledger movements resolution to add bburn movement --- lib/archethic/mining/validation_context.ex | 20 +++++--- .../replication/transaction_validator.ex | 7 +-- .../validation_stamp/ledger_operations.ex | 49 +++++++++++-------- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/lib/archethic/mining/validation_context.ex b/lib/archethic/mining/validation_context.ex index ea400a967..09b986e24 100644 --- a/lib/archethic/mining/validation_context.ex +++ b/lib/archethic/mining/validation_context.ex @@ -706,25 +706,31 @@ defmodule ArchEthic.Mining.ValidationContext do ) do initial_error = if valid_pending_transaction?, do: nil, else: :pending_transaction + validation_time = DateTime.utc_now() + + usd_price = + validation_time + |> OracleChain.get_uco_price() + |> Keyword.fetch!(:usd) + validation_stamp = %ValidationStamp{ timestamp: DateTime.utc_now(), proof_of_work: do_proof_of_work(tx), proof_of_integrity: TransactionChain.proof_of_integrity([tx, prev_tx]), - proof_of_election: - Election.validation_nodes_election_seed_sorting(tx, DateTime.utc_now()), + proof_of_election: Election.validation_nodes_election_seed_sorting(tx, validation_time), ledger_operations: %LedgerOperations{ - transaction_movements: - tx - |> Transaction.get_movements() - |> LedgerOperations.resolve_transaction_movements(DateTime.utc_now()), fee: Fee.calculate( tx, - OracleChain.get_uco_price(DateTime.utc_now()) |> Keyword.fetch!(:usd) + usd_price ) } + |> LedgerOperations.resolve_transaction_movements( + Transaction.get_movements(tx), + validation_time + ) |> LedgerOperations.from_transaction(tx) |> LedgerOperations.consume_inputs(tx.address, unspent_outputs), recipients: resolve_transaction_recipients(tx), diff --git a/lib/archethic/replication/transaction_validator.ex b/lib/archethic/replication/transaction_validator.ex index 8f40eeeea..b4a9c91c6 100644 --- a/lib/archethic/replication/transaction_validator.ex +++ b/lib/archethic/replication/transaction_validator.ex @@ -390,12 +390,9 @@ defmodule ArchEthic.Replication.TransactionValidator do previous_unspent_outputs ) do %LedgerOperations{ - fee: get_transaction_fee(tx), - transaction_movements: - tx - |> Transaction.get_movements() - |> LedgerOperations.resolve_transaction_movements(timestamp) + fee: get_transaction_fee(tx) } + |> LedgerOperations.resolve_transaction_movements(Transaction.get_movements(tx), timestamp) |> LedgerOperations.from_transaction(tx) |> LedgerOperations.consume_inputs(tx.address, previous_unspent_outputs) end 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 595c791cd..068cae7a9 100644 --- a/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations.ex +++ b/lib/archethic/transaction_chain/transaction/validation_stamp/ledger_operations.ex @@ -518,35 +518,44 @@ defmodule ArchEthic.TransactionChain.Transaction.ValidationStamp.LedgerOperation tx_movements, timestamp = %DateTime{} ) do - expected_movements = [ - %TransactionMovement{ - to: @burning_address, - amount: fee, - type: :UCO - } - | resolve_transaction_movements(tx_movements, timestamp) - ] + %__MODULE__{transaction_movements: expected_movements} = + resolve_transaction_movements(%__MODULE__{fee: fee}, tx_movements, timestamp) Enum.all?(resolved_transaction_movements, &(&1 in expected_movements)) end @doc """ - Resolve the last transaction addresses from the transaction movements + Resolve the transaction movements including the transaction's fee burning and retrieval of the last transaction addresses """ - @spec resolve_transaction_movements(list(TransactionMovement.t()), DateTime.t()) :: - list(TransactionMovement.t()) + @spec resolve_transaction_movements(t(), list(TransactionMovement.t()), DateTime.t()) :: t() def resolve_transaction_movements( + ops = %__MODULE__{fee: fee}, tx_movements, timestamp = %DateTime{} ) do - tx_movements - |> Task.async_stream( - fn mvt = %TransactionMovement{to: to} -> - %{mvt | to: TransactionChain.resolve_last_address(to, timestamp)} - end, - on_timeout: :kill_task - ) - |> Stream.filter(&match?({:ok, _}, &1)) - |> Enum.into([], fn {:ok, res} -> res end) + burn_movement = %TransactionMovement{ + to: @burning_address, + amount: fee, + type: :UCO + } + + resolved_movements = + tx_movements + |> Task.async_stream( + fn mvt = %TransactionMovement{to: to} -> + %{mvt | to: TransactionChain.resolve_last_address(to, timestamp)} + end, + on_timeout: :kill_task + ) + |> Stream.filter(&match?({:ok, _}, &1)) + |> Enum.reduce([burn_movement], fn {:ok, res}, acc -> + [res | acc] + end) + |> Enum.reverse() + + %{ + ops + | transaction_movements: resolved_movements + } end end