Skip to content

Commit

Permalink
Fix last network address in verification tx
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel authored and samuelmanzanera committed Aug 31, 2022
1 parent 054a473 commit f1bb2bc
Show file tree
Hide file tree
Showing 2 changed files with 352 additions and 6 deletions.
14 changes: 8 additions & 6 deletions lib/archethic/mining/pending_transaction_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}} ->
Expand Down Expand Up @@ -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" => _}} ->
Expand Down
344 changes: 344 additions & 0 deletions test/archethic/mining/pending_transaction_validation_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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: <<public_key::binary, certificate_size::16, certificate::binary>>
}
)

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
Expand Down

0 comments on commit f1bb2bc

Please sign in to comment.