Skip to content

Commit

Permalink
Add timeout error to the ValidateSmartContractCall message
Browse files Browse the repository at this point in the history
  • Loading branch information
Neylix committed Apr 17, 2024
1 parent 9238407 commit b212ffd
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 11 deletions.
1 change: 1 addition & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,4 @@ config :archethic, Archethic.Contracts.Interpreter.Library.Common.HttpImpl,
timeout: 500

config :archethic, Archethic.P2P.Message.GetUnspentOutputs, threshold: 1_000
config :archethic, Archethic.P2P.Message.ValidateSmartContractCall, timeout: 50
5 changes: 3 additions & 2 deletions lib/archethic/mining/smart_contract_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ defmodule Archethic.Mining.SmartContractValidation do
%SmartContractCallValidation{status: {:error, :invalid_condition, _}} -> 2
%SmartContractCallValidation{status: {:error, :invalid_execution, _}} -> 3
%SmartContractCallValidation{status: {:error, :insufficient_funds}} -> 4
%SmartContractCallValidation{status: {:error, :parsing_error, _}} -> 5
%SmartContractCallValidation{status: {:error, :transaction_not_exists}} -> 6
%SmartContractCallValidation{status: {:error, :timeout}} -> 5
%SmartContractCallValidation{status: {:error, :parsing_error, _}} -> 6
%SmartContractCallValidation{status: {:error, :transaction_not_exists}} -> 7
end)
|> List.first()
end
Expand Down
6 changes: 6 additions & 0 deletions lib/archethic/p2p/message/smart_contract_call_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule Archethic.P2P.Message.SmartContractCallValidation do
@type t :: %__MODULE__{
status:
:ok
| {:error, :timeout}
| {:error, :transaction_not_exists}
| {:error, :insufficient_funds}
| {:error, :invalid_execution, Failure.t()}
Expand Down Expand Up @@ -50,6 +51,8 @@ defmodule Archethic.P2P.Message.SmartContractCallValidation do
defp serialize_status({:error, :parsing_error, reason}),
do: <<5::8, VarInt.from_value(byte_size(reason))::binary, reason::binary>>

defp serialize_status({:error, :timeout}), do: <<6::8>>

@doc """
Deserialize the encoded message
"""
Expand Down Expand Up @@ -86,4 +89,7 @@ defmodule Archethic.P2P.Message.SmartContractCallValidation do
<<reason::binary-size(reason_size), rest::bitstring>> = rest
{{:error, :parsing_error, reason}, rest}
end

defp deserialize_status(<<6::8, rest::bitstring>>),
do: {{:error, :timeout}, rest}
end
27 changes: 18 additions & 9 deletions lib/archethic/p2p/message/validate_smart_contract_call.ex
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,24 @@ defmodule Archethic.P2P.Message.ValidateSmartContractCall do
},
_
) do
# We use job cache to reduce the number of times the contract is executed by the same node
Archethic.Utils.JobCache.get!(
{:smart_contract_validation, recipient_address, tx_address,
DateTime.to_unix(timestamp, :millisecond)},
function: fn -> validate_smart_contract_call(msg) end,
timeout: 3_000,
# We set the maximum timeout for a transaction to be processed before the kill the cache
ttl: 60_000
)
try do
# We use job cache to reduce the number of times the contract is executed by the same node
Archethic.Utils.JobCache.get!(
{:smart_contract_validation, recipient_address, tx_address,
DateTime.to_unix(timestamp, :millisecond)},
function: fn -> validate_smart_contract_call(msg) end,
timeout: Application.get_env(:archethic, __MODULE__, []) |> Keyword.get(:timeout, 4_500),
# We set the maximum timeout for a transaction to be processed before the kill the cache
ttl: 60_000
)
catch
:exit, _ ->
%SmartContractCallValidation{
status: {:error, :timeout},
fee: 0,
last_chain_sync_date: DateTime.from_unix!(0)
}
end
end

defp validate_smart_contract_call(%__MODULE__{
Expand Down
32 changes: 32 additions & 0 deletions test/archethic/p2p/message/validate_smart_contract_call_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,38 @@ defmodule Archethic.P2P.Message.ValidateSmartContractCallTest do
|> ValidateSmartContractCall.process(:crypto.strong_rand_bytes(32))
end

test "should return a timeout" do
tx =
~s"""
@version 1
condition triggered_by: transaction do
true
end
actions triggered_by: transaction do
Contract.set_content "hello"
end
"""
|> ContractFactory.create_valid_contract_tx()

MockDB
|> expect(:get_transaction, fn _, _, _ ->
# timeout is set to 50ms
Process.sleep(1_000)
{:ok, tx}
end)

incoming_tx = TransactionFactory.create_valid_transaction([], content: "hola")

assert %SmartContractCallValidation{status: {:error, :timeout}} =
%ValidateSmartContractCall{
recipient: %Recipient{address: random_address()},
transaction: incoming_tx,
timestamp: DateTime.utc_now()
}
|> ValidateSmartContractCall.process(random_public_key())
end

test "should validate smart contract call with named action and return valid message" do
tx =
~s"""
Expand Down

0 comments on commit b212ffd

Please sign in to comment.