Skip to content

Commit

Permalink
Define the limit on the P2P message instead of GraphQL
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelmanzanera committed Sep 15, 2022
1 parent a6a2eb7 commit df2eacf
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 19 deletions.
8 changes: 4 additions & 4 deletions lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,17 @@ defmodule Archethic do
@doc """
Request to fetch the inputs for a transaction address from the closest nodes at a given page
"""
@spec get_transaction_inputs(binary(), non_neg_integer()) :: list(TransactionInput.t())
def get_transaction_inputs(address, page)
when is_binary(address) and is_integer(page) and page >= 0 do
@spec get_transaction_inputs(binary(), paging_offset :: non_neg_integer(), limit ::non_neg_integer()) :: list(TransactionInput.t())
def get_transaction_inputs(address, page, limit)
when is_binary(address) and is_integer(page) and page >= 0 and is_integer(limit) and limit >= 0 do
nodes =
address
|> Election.chain_storage_nodes(P2P.authorized_and_available_nodes())
|> P2P.nearest_nodes()
|> Enum.filter(&Node.locally_available?/1)

{inputs, _more?, _offset} =
TransactionChain.fetch_inputs_remotely(address, nodes, DateTime.utc_now(), page)
TransactionChain.fetch_inputs_remotely(address, nodes, DateTime.utc_now(), page, limit)

inputs
end
Expand Down
21 changes: 15 additions & 6 deletions lib/archethic/p2p/message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,8 @@ defmodule Archethic.P2P.Message do
<<16::8, address::binary>>
end

def encode(%GetTransactionInputs{address: address, offset: offset}) do
<<17::8, address::binary, VarInt.from_value(offset)::binary>>
def encode(%GetTransactionInputs{address: address, offset: offset, limit: limit}) do
<<17::8, address::binary, VarInt.from_value(offset)::binary, VarInt.from_value(limit)::binary>>
end

def encode(%GetTransactionChainLength{address: address}) do
Expand Down Expand Up @@ -829,7 +829,8 @@ defmodule Archethic.P2P.Message do
def decode(<<17::8, rest::bitstring>>) do
{address, rest} = Utils.deserialize_address(rest)
{offset, rest} = VarInt.get_value(rest)
{%GetTransactionInputs{address: address, offset: offset}, rest}
{limit, rest} = VarInt.get_value(rest)
{%GetTransactionInputs{address: address, offset: offset, limit: limit}, rest}
end

def decode(<<18::8, rest::bitstring>>) do
Expand Down Expand Up @@ -1500,7 +1501,7 @@ defmodule Archethic.P2P.Message do
}
end

def process(%GetTransactionInputs{address: address, offset: offset}) do
def process(%GetTransactionInputs{address: address, offset: offset, limit: limit}) do
contract_inputs =
address
|> Contracts.list_contract_transactions()
Expand All @@ -1524,8 +1525,16 @@ defmodule Archethic.P2P.Message do
|> byte_size()

input_size = TransactionInput.serialize(input) |> byte_size

size_capacity? = acc_size + input_size < 3_000_000

if acc_size + input_size < 3_000_000 do
should_take_more? = if limit > 0 do
length(acc.inputs) < limit and size_capacity?
else
size_capacity?
end

if should_take_more? do
new_acc =
acc
|> Map.update!(:inputs, &[input | &1])
Expand All @@ -1539,7 +1548,7 @@ defmodule Archethic.P2P.Message do
end)

%TransactionInputList{
inputs: inputs,
inputs: Enum.reverse(inputs),
more?: more?,
offset: offset
}
Expand Down
5 changes: 3 additions & 2 deletions lib/archethic/p2p/message/get_transaction_inputs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ defmodule Archethic.P2P.Message.GetTransactionInputs do
Represents a message with to request the inputs (spent or unspents) from a transaction
"""
@enforce_keys [:address]
defstruct [:address, offset: 0]
defstruct [:address, offset: 0, limit: 0]

alias Archethic.Crypto

@type t :: %__MODULE__{
address: Crypto.versioned_hash(),
offset: non_neg_integer()
offset: non_neg_integer(),
limit: non_neg_integer()
}
end
12 changes: 6 additions & 6 deletions lib/archethic/transaction_chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -752,13 +752,13 @@ defmodule Archethic.TransactionChain do
If the inputs exist, then they are returned in the shape of `{:ok, inputs}`.
If no nodes are able to answer the request, `{:error, :network_issue}` is returned.
"""
@spec fetch_inputs_remotely(address :: Crypto.versioned_hash(), list(Node.t()), DateTime.t()) ::
@spec fetch_inputs_remotely(address :: Crypto.versioned_hash(), list(Node.t()), DateTime.t(), limit :: non_neg_integer()) ::
{inputs :: list(TransactionInput.t()), more? :: boolean(), offset :: non_neg_integer()}
def fetch_inputs_remotely(address, nodes, timestamp, offset \\ 0)
def fetch_inputs_remotely(_, [], _, _), do: {[], false, 0}
def fetch_inputs_remotely(address, nodes, timestamp, offset \\ 0, limit \\ 0)
def fetch_inputs_remotely(_, [], _, _, _), do: {[], false, 0}

def fetch_inputs_remotely(address, nodes, timestamp = %DateTime{}, offset)
when is_binary(address) and is_list(nodes) and is_integer(offset) and offset >= 0 do
def fetch_inputs_remotely(address, nodes, timestamp = %DateTime{}, offset, limit)
when is_binary(address) and is_list(nodes) and is_integer(offset) and offset >= 0 and is_integer(limit) and limit >= 0 do
conflict_resolver = fn results ->
results
|> Enum.sort_by(&length(&1.inputs), :desc)
Expand All @@ -767,7 +767,7 @@ defmodule Archethic.TransactionChain do

case P2P.quorum_read(
nodes,
%GetTransactionInputs{address: address, offset: offset},
%GetTransactionInputs{address: address, offset: offset, limit: limit},
conflict_resolver
) do
{:ok, %TransactionInputList{inputs: inputs, more?: more?, offset: offset}} ->
Expand Down
2 changes: 1 addition & 1 deletion lib/archethic_web/graphql_schema/resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do
def get_inputs(address, paging_offset \\ 0, limit \\ 0) do
inputs =
address
|> Archethic.get_transaction_inputs(paging_offset)
|> Archethic.get_transaction_inputs(paging_offset, limit)
|> Enum.map(&TransactionInput.to_map/1)

case limit do
Expand Down

0 comments on commit df2eacf

Please sign in to comment.