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 8abd27f
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 19 deletions.
13 changes: 9 additions & 4 deletions lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,22 @@ 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
23 changes: 17 additions & 6 deletions lib/archethic/p2p/message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,9 @@ 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 +830,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 +1502,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 @@ -1525,7 +1527,16 @@ defmodule Archethic.P2P.Message do

input_size = TransactionInput.serialize(input) |> byte_size

if acc_size + input_size < 3_000_000 do
size_capacity? = acc_size + input_size < 3_000_000

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 +1550,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
18 changes: 12 additions & 6 deletions lib/archethic/transaction_chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -752,13 +752,19 @@ 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 +773,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 8abd27f

Please sign in to comment.