Skip to content

Commit

Permalink
Enhance_validation_of_keychain_keychain_access_transaction_#882
Browse files Browse the repository at this point in the history
  • Loading branch information
apoorv-2204 committed Mar 15, 2023
1 parent 9c935db commit 496b009
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 48 deletions.
54 changes: 34 additions & 20 deletions lib/archethic/mining/pending_transaction_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -512,22 +512,31 @@ defmodule Archethic.Mining.PendingTransactionValidation do
do: {:error, "No recipient specified in code approval"}

defp do_accept_transaction(
%Transaction{
type: :keychain,
data: %TransactionData{content: "", ownerships: []}
},
%Transaction{type: :keychain, data: %TransactionData{content: ""}},
_
) do
{:error, "Invalid Keychain transaction"}
end
),
do: {:error, "Invalid Keychain transaction"}

defp do_accept_transaction(
%Transaction{type: :keychain, data: %TransactionData{ownerships: []}},
_
),
do: {:error, "Invalid Keychain transaction"}

defp do_accept_transaction(
%Transaction{
type: :keychain,
data: %TransactionData{content: content, ownerships: _ownerships}
data: %TransactionData{
content: content,
ledger: %Ledger{
uco: %UCOLedger{transfers: []},
token: %TokenLedger{transfers: []}
}
}
},
_
) do
# ownerships validate in :ok <- validate_ownerships(tx),
with {:ok, json_did} <- Jason.decode(content),
:ok <- ExJsonSchema.Validator.validate(@did_schema, json_did) do
:ok
Expand All @@ -541,31 +550,36 @@ defmodule Archethic.Mining.PendingTransactionValidation do
end
end

defp do_accept_transaction(
%Transaction{
type: :keychain_access,
data: %TransactionData{ownerships: []}
},
_
) do
{:error, "Invalid Keychain access transaction"}
end
defp do_accept_transaction(%Transaction{type: :keychain, data: _}, _),
do: {:error, "Invalid Keychain transaction"}

defp do_accept_transaction(
%Transaction{
type: :keychain_access,
data: %TransactionData{ownerships: ownerships},
previous_public_key: previous_public_key
previous_public_key: previous_public_key,
data: %TransactionData{
content: "",
ownerships: [ownership = %Ownership{secret: _, authorized_keys: _}],
ledger: %Ledger{
uco: %UCOLedger{transfers: []},
token: %TokenLedger{transfers: []}
}
}
},
_
) do
if Enum.any?(ownerships, &Ownership.authorized_public_key?(&1, previous_public_key)) do
# ownerships validate in :ok <- validate_ownerships(tx),
# forbid empty ownership or more than one secret, content, uco & token transfers
if Ownership.authorized_public_key?(ownership, previous_public_key) do
:ok
else
{:error, "Invalid Keychain access transaction - Previous public key must be authorized"}
end
end

defp do_accept_transaction(%Transaction{type: :keychain_access}, _),
do: {:error, "Invalid Keychain Access transaction"}

defp do_accept_transaction(
%Transaction{
type: :token,
Expand Down
2 changes: 1 addition & 1 deletion src/c/nat/miniupnp
237 changes: 210 additions & 27 deletions test/archethic/mining/pending_transaction_validation_test.exs
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
defmodule Archethic.Mining.PendingTransactionValidationTest do
use ArchethicCase, async: false

alias Archethic.{
Crypto,
Mining.PendingTransactionValidation,
P2P,
P2P.Node,
Reward.Scheduler,
SharedSecrets,
TransactionChain
}
alias Archethic.{Crypto, P2P, P2P.Node, P2P.Message, SharedSecrets, TransactionChain}
alias Archethic.{Mining.PendingTransactionValidation, Reward.Scheduler}

alias SharedSecrets.{MemTables.NetworkLookup, MemTables.OriginKeyLookup}
alias Message.{FirstPublicKey, GetFirstPublicKey, GetTransactionSummary, NotFound}
alias TransactionChain.{Transaction, TransactionData}
alias TransactionData.{Ledger, Ownership, TokenLedger, UCOLedger}

alias Archethic.Governance.Pools.MemTable, as: PoolsMemTable
alias Archethic.SharedSecrets.{MemTables.NetworkLookup, MemTables.OriginKeyLookup}

alias Archethic.P2P.Message.{
FirstPublicKey,
GetFirstPublicKey,
GetTransactionSummary,
NotFound
}

alias TransactionChain.{
Transaction,
TransactionData,
TransactionData.Ledger,
TransactionData.UCOLedger,
TransactionData.UCOLedger.Transfer,
TransactionData.Ownership
}
alias TokenLedger.Transfer, as: TokenTransfer
alias UCOLedger.Transfer, as: UCOTransfer

import Mox

Expand Down Expand Up @@ -914,7 +897,7 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do
ledger: %Ledger{
uco: %UCOLedger{
transfers: [
%Transfer{to: :crypto.strong_rand_bytes(32), amount: 100_000}
%UCOTransfer{to: :crypto.strong_rand_bytes(32), amount: 100_000}
]
}
},
Expand Down Expand Up @@ -944,4 +927,204 @@ defmodule Archethic.Mining.PendingTransactionValidationTest do
assert :ok = PendingTransactionValidation.validate(tx)
end
end

describe "Keychain Transaction" do
test "should reject empty content in keychain transaction" do
tx_seed = :crypto.strong_rand_bytes(32)

tx =
Transaction.new(
:keychain,
%TransactionData{
content: ""
},
tx_seed,
0
)

assert {:error, "Invalid Keychain transaction"} = PendingTransactionValidation.validate(tx)
end

test "Should Reject keychain tx with empty Ownerships list in keychain transaction" do
tx_seed = :crypto.strong_rand_bytes(32)

tx =
Transaction.new(
:keychain,
%TransactionData{
content: "content",
ownerships: []
},
tx_seed,
0
)

assert {:error, "Invalid Keychain transaction"} = PendingTransactionValidation.validate(tx)
end

test "Should Reject keychain tx with UCO tranfers" do
tx_seed = :crypto.strong_rand_bytes(32)

tx =
Transaction.new(
:keychain,
%TransactionData{
content: "content",
ownerships: [
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
])
],
ledger: %Ledger{
uco: %UCOLedger{
transfers: [
%UCOTransfer{to: :crypto.strong_rand_bytes(32), amount: 100_000}
]
}
}
},
tx_seed,
0
)

assert {:error, "Invalid Keychain transaction"} = PendingTransactionValidation.validate(tx)

tx =
Transaction.new(
:keychain,
%TransactionData{
content: "content",
ownerships: [
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
])
],
ledger: %Ledger{
token: %TokenLedger{
transfers: [
%TokenTransfer{
to: :crypto.strong_rand_bytes(32),
amount: 100_000_000,
token_address: "0123"
}
]
}
}
},
tx_seed,
0
)

assert {:error, "Invalid Keychain transaction"} = PendingTransactionValidation.validate(tx)

tx =
Transaction.new(
:keychain,
%TransactionData{
content: "content",
ownerships: [
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
])
],
ledger: %Ledger{
uco: %UCOLedger{
transfers: [
%UCOTransfer{to: :crypto.strong_rand_bytes(32), amount: 100_000}
]
},
token: %TokenLedger{
transfers: [
%TokenTransfer{
to: :crypto.strong_rand_bytes(32),
amount: 100_000_000,
token_address: "0123"
}
]
}
}
},
tx_seed,
0
)

assert {:error, "Invalid Keychain transaction"} = PendingTransactionValidation.validate(tx)
end
end

describe "Keychain Acesss Transaction" do
test "should reject tx with more than one ownership" do
tx_seed = :crypto.strong_rand_bytes(32)

tx =
Transaction.new(
:keychain_access,
%TransactionData{
ownerships: [
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
]),
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
])
]
},
tx_seed,
0
)

assert {:error, "Invalid Keychain Access transaction"} =
PendingTransactionValidation.validate(tx)

tx =
Transaction.new(
:keychain_access,
%TransactionData{
ownerships: []
},
tx_seed,
0
)

assert {:error, "Invalid Keychain Access transaction"} =
PendingTransactionValidation.validate(tx)

tx =
Transaction.new(
:keychain_access,
%TransactionData{
content: "content",
ownerships: [
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
])
]
},
tx_seed,
0
)

assert {:error, "Invalid Keychain Access transaction"} =
PendingTransactionValidation.validate(tx)

tx =
Transaction.new(
:keychain_access,
%TransactionData{
content: "",
ownerships: [
Ownership.new(tx_seed, :crypto.strong_rand_bytes(32), [
Crypto.storage_nonce_public_key()
])
]
},
tx_seed,
0
)

assert {:error,
"Invalid Keychain access transaction - Previous public key must be authorized"} =
PendingTransactionValidation.validate(tx)
end
end
end

0 comments on commit 496b009

Please sign in to comment.