Skip to content

Commit

Permalink
Infinite looping in forward transaction #931
Browse files Browse the repository at this point in the history
  • Loading branch information
apoorv-2204 committed Mar 14, 2023
1 parent 21037c7 commit d0fda0c
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 7 deletions.
14 changes: 9 additions & 5 deletions lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,16 @@ defmodule Archethic do
)

defp forward_transaction(tx, welcome_node_key, [node | rest]) do
case P2P.send_message(node, %NewTransaction{transaction: tx, welcome_node: welcome_node_key}) do
{:ok, %Ok{}} ->
:ok
if node.first_public_key == welcome_node_key do
forward_transaction(tx, welcome_node_key, rest)
else
case P2P.send_message(node, %NewTransaction{transaction: tx, welcome_node: welcome_node_key}) do
{:ok, %Ok{}} ->
:ok

{:error, _} ->
forward_transaction(tx, welcome_node_key, rest)
{:error, _} ->
forward_transaction(tx, welcome_node_key, rest)
end
end
end

Expand Down
94 changes: 92 additions & 2 deletions test/archethic_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ defmodule ArchethicTest do
assert :ok = Archethic.send_new_transaction(tx)
end

test "When NOT synced should forward the tx and start repair " do
test "should return error when node not synced,and try to forward the tx to itself " do
nss_genesis_address = "nss_genesis_address"
nss_last_address = "nss_last_address"
:persistent_term.put(:node_shared_secrets_gen_addr, nss_genesis_address)
Expand Down Expand Up @@ -101,7 +101,7 @@ defmodule ArchethicTest do
)

MockClient
|> expect(:send_message, 4, fn
|> expect(:send_message, 3, fn
# validate nss chain from network
# anticippated to be failed
_, %GetLastTransactionAddress{}, _ ->
Expand All @@ -121,6 +121,96 @@ defmodule ArchethicTest do
# last address is d/f it returns last address from quorum
assert {:error, "willnotmatchaddress"} = SharedSecrets.verify_synchronization()

# trying to ssend a tx when NSS chain not synced
tx = Transaction.new(:transfer, %TransactionData{}, "seed", 0)
assert {:error, :network_issue} = Archethic.send_new_transaction(tx)

# start repair and should bottleneck requests
pid = SelfRepair.repair_in_progress?(nss_genesis_address)
Process.sleep(150)
assert pid != nil
end

test "should forward tx to other nodes " do
nss_genesis_address = "nss_genesis_address"
nss_last_address = "nss_last_address"
:persistent_term.put(:node_shared_secrets_gen_addr, nss_genesis_address)
first_pb_key = Crypto.first_node_public_key()

P2P.add_and_connect_node(%Node{
ip: {127, 0, 0, 1},
port: 3000,
first_public_key: Crypto.first_node_public_key(),
last_public_key: Crypto.first_node_public_key(),
network_patch: "AAA",
geo_patch: "AAA",
available?: true,
authorized?: true,
authorization_date: DateTime.utc_now() |> DateTime.add(-20_000)
})

node2_fpbk = "node2"

P2P.add_and_connect_node(%Node{
ip: {127, 0, 0, 1},
port: 3000,
first_public_key: node2_fpbk,
last_public_key: node2_fpbk,
network_patch: "AAA",
geo_patch: "AAA",
available?: true,
authorized?: true,
authorization_date: DateTime.utc_now() |> DateTime.add(-20_000)
})

start_supervised!({SummaryTimer, Application.get_env(:archethic, SummaryTimer)})

MockDB
|> stub(:get_last_chain_address, fn ^nss_genesis_address ->
{nss_last_address, DateTime.utc_now()}
end)
|> stub(
:get_transaction,
fn
^nss_last_address, [validation_stamp: [:timestamp]], :chain ->
{:ok,
%Transaction{
validation_stamp: %{
__struct__: :ValidationStamp,
# fail mathematical check with irregular timestamp
# causes validate_scheduling_time() to fail
timestamp: DateTime.utc_now() |> DateTime.add(-86_400)
}
}}

_, _, _ ->
{:error, :transaction_not_exists}
end
)

MockClient
|> expect(:send_message, 5, fn
# validate nss chain from network
# anticippated to be failed
_, %GetLastTransactionAddress{}, _ ->
{:ok, %LastTransactionAddress{address: "willnotmatchaddress"}}

%Node{first_public_key: ^node2_fpbk},
%NewTransaction{transaction: _, welcome_node: ^first_pb_key},
_ ->
# forward the tx
{:ok, %Ok{}}

_, %GetTransaction{address: _}, _ ->
{:ok, %NotFound{}}

_, _, _ ->
{:ok, %Ok{}}
end)

# last address is d/f it returns last address from quorum
assert {:error, "willnotmatchaddress"} = SharedSecrets.verify_synchronization()

# trying to ssend a tx when NSS chain not synced
tx = Transaction.new(:transfer, %TransactionData{}, "seed", 0)
assert :ok = Archethic.send_new_transaction(tx)
Expand Down

0 comments on commit d0fda0c

Please sign in to comment.