Skip to content

Commit

Permalink
fix: filter contracts after account balance dry-run on blockhash (#861)
Browse files Browse the repository at this point in the history
  • Loading branch information
jyeshe committed Aug 23, 2022
1 parent 654228e commit 40da750
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 18 deletions.
6 changes: 4 additions & 2 deletions lib/ae_mdw/aex9.ex
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ defmodule AeMdw.Aex9 do

account_presences =
Enum.map(account_presence_keys, fn {^account_pk, contract_pk} ->
{amount, _height_hash} = Db.aex9_balance(contract_pk, account_pk, type_height_hash)
{:ok, {amount, _height_hash}} =
Db.aex9_balance(contract_pk, account_pk, type_height_hash)

Model.aexn_contract(meta_info: {name, symbol, _dec}) =
State.fetch!(state, Model.AexnContract, {:aex9, contract_pk})
Expand Down Expand Up @@ -360,7 +361,8 @@ defmodule AeMdw.Aex9 do
defp render_balance_history_item(contract_pk, account_pk, gen) do
type_height_hash = {:key, gen, DbUtil.height_hash(gen)}

{amount_or_nil, _height_hash} = Db.aex9_balance(contract_pk, account_pk, type_height_hash)
{:ok, {amount_or_nil, _height_hash}} =
Db.aex9_balance(contract_pk, account_pk, type_height_hash)

balance = render_balance(contract_pk, {:address, account_pk}, amount_or_nil)

Expand Down
2 changes: 1 addition & 1 deletion lib/ae_mdw/error.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ defmodule AeMdw.Error do
def to_string(Input.NotAex9, x), do: concat("not AEX9 contract", x)
def to_string(Input.NotAex141, x), do: concat("not AEX141 contract", x)
def to_string(Input.ContractReturn, x), do: concat("invalid return of contract", x)
def to_string(Input.Aex9BalanceNotAvailable, x), do: concat("balance is not yet available", x)
def to_string(Input.Aex9BalanceNotAvailable, x), do: concat("balance is not available", x)
def to_string(Input.Base64, x), do: concat("invalid base64 encoding", x)
def to_string(Input.Hex32, x), do: concat("invalid hex32 encoding", x)
def to_string(Input.RangeTooBig, x), do: concat("invalid range", x)
Expand Down
14 changes: 9 additions & 5 deletions lib/ae_mdw/node/db.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule AeMdw.Node.Db do
@type hash_type() :: nil | :key | :micro
@type height_hash() :: {hash_type(), pos_integer(), binary()}
@type balances_map() :: %{{:address, pubkey()} => integer()}
@type account_balance() :: {integer() | nil, height_hash()}
@opaque key_block() :: tuple()
@opaque micro_block() :: tuple()

Expand Down Expand Up @@ -157,22 +158,25 @@ defmodule AeMdw.Node.Db do
{type, :aec_headers.height(header), ok!(:aec_headers.hash_header(header))}
end

@spec aex9_balance(pubkey(), pubkey()) :: {integer() | nil, height_hash()}
@spec aex9_balance(pubkey(), pubkey()) ::
{:ok, account_balance()} | {:error, Runner.call_error()}
def aex9_balance(contract_pk, account_pk),
do: aex9_balance(contract_pk, account_pk, false)

@spec aex9_balance(pubkey(), pubkey(), boolean()) :: {integer() | nil, height_hash()}
@spec aex9_balance(pubkey(), pubkey(), boolean()) ::
{:ok, account_balance()} | {:error, Runner.call_error()}
def aex9_balance(contract_pk, account_pk, the_very_top?) when is_boolean(the_very_top?),
do: aex9_balance(contract_pk, account_pk, top_height_hash(the_very_top?))

@spec aex9_balance(pubkey(), pubkey(), height_hash()) ::
{integer() | nil, height_hash()}
{:ok, account_balance()} | {:error, Runner.call_error()}
def aex9_balance(contract_pk, account_pk, {type, height, hash}) do
case Runner.call_contract(contract_pk, {type, height, hash}, "balance", [
{:address, account_pk}
]) do
{:ok, {:variant, [0, 1], 1, {amt}}} -> {amt, {type, height, hash}}
{:ok, {:variant, [0, 1], 0, {}}} -> {nil, {type, height, hash}}
{:ok, {:variant, [0, 1], 1, {amt}}} -> {:ok, {amt, {type, height, hash}}}
{:ok, {:variant, [0, 1], 0, {}}} -> {:ok, {nil, {type, height, hash}}}
{:error, reason} -> {:error, reason}
end
end

Expand Down
28 changes: 19 additions & 9 deletions lib/ae_mdw_web/controllers/aex9_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule AeMdwWeb.Aex9Controller do
alias AeMdw.AexnContracts
alias AeMdw.Db.Contract
alias AeMdw.Db.Model
alias AeMdw.Db.Origin
alias AeMdw.Db.State
alias AeMdw.Db.Util
alias AeMdw.Error.Input, as: ErrInput
Expand Down Expand Up @@ -310,7 +311,13 @@ defmodule AeMdwWeb.Aex9Controller do
defp balance_reply(%Conn{assigns: %{state: state, opts: opts}} = conn, contract_pk, account_pk) do
{amount, {type, height, hash}} =
if top?(opts) do
DBN.aex9_balance(contract_pk, account_pk, top?(opts))
case DBN.aex9_balance(contract_pk, account_pk, top?(opts)) do
{:ok, account_balance} ->
account_balance

{:error, reason} ->
{:error, ErrInput.Aex9BalanceNotAvailable.exception(value: reason)}
end
else
case Aex9.fetch_amount_and_keyblock(state, contract_pk, account_pk) do
{:ok, {amount, kb_height_hash}} ->
Expand All @@ -334,7 +341,7 @@ defmodule AeMdwWeb.Aex9Controller do
map_balances_range(
range,
fn type_height_hash ->
{amount, _} = DBN.aex9_balance(contract_pk, account_pk, type_height_hash)
{:ok, {amount, _}} = DBN.aex9_balance(contract_pk, account_pk, type_height_hash)
{:amount, amount}
end
)
Expand All @@ -348,7 +355,7 @@ defmodule AeMdwWeb.Aex9Controller do
account_pk,
{_type, _height, _hash} = height_hash
) do
{amount, _} = DBN.aex9_balance(contract_pk, account_pk, height_hash)
{:ok, {amount, _}} = DBN.aex9_balance(contract_pk, account_pk, height_hash)
json(conn, balance_to_map({amount, height_hash}, contract_pk, account_pk))
end

Expand Down Expand Up @@ -377,17 +384,20 @@ defmodule AeMdwWeb.Aex9Controller do
account_pk,
{kbi, mbi} = block_index
) do
{:ok, Model.block(tx_index: block_txi, hash: block_hash)} =
State.get(state, Model.Block, block_index)
Model.block(hash: block_hash) = State.fetch!(state, Model.Block, block_index)

type = if mbi == -1, do: :key, else: :micro

balances =
state
|> Contract.aex9_search_contract(account_pk, block_txi)
|> Enum.map(fn {contract_pk, last_txi} ->
{amount, _} = DBN.aex9_balance(contract_pk, account_pk, {type, kbi, block_hash})
{amount, last_txi, contract_pk}
|> Contract.aex9_search_contracts(account_pk)
|> Enum.flat_map(fn contract_pk ->
create_txi = Origin.tx_index!(state, {:contract, contract_pk})

case DBN.aex9_balance(contract_pk, account_pk, {type, kbi, block_hash}) do
{:ok, {amount, _}} when amount != nil -> [{amount, create_txi, contract_pk}]
_missing -> []
end
end)
|> Enum.map(&balance_to_map(state, &1))

Expand Down
2 changes: 1 addition & 1 deletion lib/ae_mdw_web/views/aexn_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule AeMdwWeb.AexnView do
@spec balance_to_map(State.t(), {non_neg_integer(), non_neg_integer(), pubkey()}) ::
map()
def balance_to_map(state, {amount, call_txi, contract_pk}) do
Model.tx(id: tx_hash, block_index: {height, _mbi}) = Util.read_tx!(state, call_txi)
Model.tx(id: tx_hash, block_index: {height, _mbi}) = State.fetch!(state, Model.Tx, call_txi)

{block_hash, tx_type, _signed_tx, _tx_rec} = NodeDb.get_tx_data(tx_hash)

Expand Down
13 changes: 13 additions & 0 deletions test/ae_mdw_web/controllers/aex9_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ defmodule AeMdwWeb.Aex9ControllerTest do
end
end

describe "balance" do
test "returns 400 when contract is unknown", %{conn: conn, store: store} do
contract_id = enc_ct(:crypto.strong_rand_bytes(32))
account_id = enc_id(:crypto.strong_rand_bytes(32))

assert %{"error" => <<"not AEX9 contract: ", ^contract_id::binary>>} =
conn
|> with_store(store)
|> get("/aex9/balance/#{contract_id}/#{account_id}")
|> json_response(400)
end
end

describe "balances" do
test "returns all account balances", %{conn: conn, store: store} do
account_pk = :crypto.strong_rand_bytes(32)
Expand Down

0 comments on commit 40da750

Please sign in to comment.