Skip to content

Commit a62d03f

Browse files
authored
fix: render binary pointer key on name related endpoints (#1004)
1 parent 84ba88f commit a62d03f

File tree

8 files changed

+250
-29
lines changed

8 files changed

+250
-29
lines changed

lib/ae_mdw/db/format.ex

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,22 @@ defmodule AeMdw.Db.Format do
9191
}
9292
end
9393

94+
@spec encode_pointers(list() | map()) :: %{iodata() => String.t()}
95+
def encode_pointers(pointers) when is_map(pointers) do
96+
Enum.into(pointers, %{}, fn {key, id} -> {maybe_base64_pointer_key(key), enc_id(id)} end)
97+
end
98+
99+
def encode_pointers(pointers) do
100+
Enum.map(pointers, fn
101+
%{"key" => key, "id" => id} -> %{"key" => maybe_base64_pointer_key(key), "id" => id}
102+
%{key: key, id: id} -> %{key: maybe_base64_pointer_key(key), id: id}
103+
end)
104+
end
105+
106+
@spec enc_id(aeser_id() | nil) :: nil | String.t()
107+
def enc_id(nil), do: nil
108+
def enc_id({:id, _type, _pk} = id), do: Enc.encode(:id_hash, id)
109+
94110
defp custom_raw_data(_state, :contract_create_tx, tx, tx_rec, _signed_tx, block_hash) do
95111
init_call_details = Contract.get_init_call_details(tx_rec, block_hash)
96112

@@ -134,8 +150,11 @@ defmodule AeMdw.Db.Format do
134150
put_in(tx, [:tx, :name_id], :aeser_id.create(:name, name_id))
135151
end
136152

137-
defp custom_raw_data(state, :name_update_tx, tx, tx_rec, _signed_tx, _block_hash),
138-
do: put_in(tx, [:tx, :name], Name.plain_name!(state, :aens_update_tx.name_hash(tx_rec)))
153+
defp custom_raw_data(state, :name_update_tx, tx, tx_rec, _signed_tx, _block_hash) do
154+
tx
155+
|> put_in([:tx, :name], Name.plain_name!(state, :aens_update_tx.name_hash(tx_rec)))
156+
|> update_in([:tx, :pointers], &encode_pointers/1)
157+
end
139158

140159
defp custom_raw_data(state, :name_transfer_tx, tx, tx_rec, _signed_tx, _block_hash),
141160
do: put_in(tx, [:tx, :name], Name.plain_name!(state, :aens_transfer_tx.name_hash(tx_rec)))
@@ -189,9 +208,9 @@ defmodule AeMdw.Db.Format do
189208
end
190209
)
191210

192-
raw_to_json(raw_map)
211+
raw_map
212+
|> raw_to_json()
193213
|> put_in(["auction"], auction)
194-
|> update_in(["status"], &to_string/1)
195214
end
196215

197216
def to_map(state, {call_txi, local_idx}, Model.IntContractCall) do
@@ -353,8 +372,11 @@ defmodule AeMdw.Db.Format do
353372
put_in(tx, ["name_id"], Enc.encode(:name, name_id))
354373
end
355374

356-
defp custom_encode(state, :name_update_tx, tx, tx_rec, _signed_tx, _txi, _block_hash),
357-
do: put_in(tx, ["name"], Name.plain_name!(state, :aens_update_tx.name_hash(tx_rec)))
375+
defp custom_encode(state, :name_update_tx, tx, tx_rec, _signed_tx, _txi, _block_hash) do
376+
tx
377+
|> put_in(["name"], Name.plain_name!(state, :aens_update_tx.name_hash(tx_rec)))
378+
|> update_in(["pointers"], &encode_pointers/1)
379+
end
358380

359381
defp custom_encode(state, :name_transfer_tx, tx, tx_rec, _signed_tx, _txi, _block_hash),
360382
do: put_in(tx, ["name"], Name.plain_name!(state, :aens_transfer_tx.name_hash(tx_rec)))
@@ -365,6 +387,12 @@ defmodule AeMdw.Db.Format do
365387
defp custom_encode(_state, _tx_type, tx, _tx_rec, _signed_tx, _txi, _block_hash),
366388
do: tx
367389

390+
defp maybe_base64_pointer_key(key)
391+
when key in ["account_pubkey", "oracle_pubkey", "contract_pubkey", "channel"],
392+
do: key
393+
394+
defp maybe_base64_pointer_key(key), do: Base.encode64(key)
395+
368396
defp maybe_base64(bin) do
369397
try do
370398
dec = :base64.decode(bin)
@@ -382,12 +410,6 @@ defmodule AeMdw.Db.Format do
382410
end
383411
end
384412

385-
@spec enc_id(aeser_id() | nil) :: binary() | nil
386-
def enc_id(nil), do: nil
387-
388-
def enc_id({:id, idtype, payload}),
389-
do: Enc.encode(AE.id_type(idtype), payload)
390-
391413
defp raw_to_json(x),
392414
do: map_raw_values(x, &to_json/1)
393415

lib/ae_mdw/db/name.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ defmodule AeMdw.Db.Name do
144144
end
145145

146146
pointers
147-
|> Stream.map(&pointer_kv_raw/1)
148-
|> Enum.into(%{})
147+
|> Enum.into(%{}, &pointer_kv_raw/1)
148+
|> Format.encode_pointers()
149149
end
150150

151151
@spec ownership(state(), Model.name()) :: %{

lib/ae_mdw/names.ex

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -433,18 +433,11 @@ defmodule AeMdw.Names do
433433
transfers: Enum.map(transfers, &expand_txi(state, &1, opts)),
434434
revoke: (revoke && expand_txi(state, revoke, opts)) || nil,
435435
auction_timeout: auction_timeout,
436-
pointers: render_pointers(state, name),
436+
pointers: Name.pointers(state, name),
437437
ownership: render_ownership(state, name)
438438
}
439439
end
440440

441-
defp render_pointers(state, name) do
442-
state
443-
|> Name.pointers(name)
444-
|> Enum.map(fn {key, id} -> {key, Format.enc_id(id)} end)
445-
|> Enum.into(%{})
446-
end
447-
448441
defp render_ownership(state, name) do
449442
%{current: current_owner, original: original_owner} = Name.ownership(state, name)
450443

lib/ae_mdw_web/controllers/name_controller.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ defmodule AeMdwWeb.NameController do
171171
defp pointers_reply(%Conn{assigns: %{state: state}} = conn, plain_name) do
172172
case Name.locate(state, plain_name) do
173173
{m_name, Model.ActiveName} ->
174-
json(conn, Format.map_raw_values(Name.pointers(state, m_name), &Format.to_json/1))
174+
json(conn, Name.pointers(state, m_name))
175175

176176
{_m_name, Model.InactiveName} ->
177177
raise ErrInput.Expired, value: plain_name

test/ae_mdw/db/name_test.exs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
defmodule AeMdw.Db.NameTest do
2+
use ExUnit.Case, async: false
3+
4+
alias AeMdw.Db.Format
5+
alias AeMdw.Db.Model
6+
alias AeMdw.Db.MemStore
7+
alias AeMdw.Db.Name
8+
alias AeMdw.Db.NullStore
9+
alias AeMdw.Db.State
10+
alias AeMdw.Db.Store
11+
12+
import Mock
13+
14+
require Model
15+
16+
describe "pointers/2" do
17+
test "encodes non-string pointer key to base64" do
18+
name = "binarypointer.chain"
19+
pointer_id = :aeser_id.create(:account, <<1::256>>)
20+
oracle_id = :aeser_id.create(:oracle, <<1::256>>)
21+
22+
non_string_pointer_key =
23+
<<104, 65, 117, 174, 49, 251, 29, 202, 69, 174, 147, 56, 60, 150, 188, 247, 149, 85, 150,
24+
148, 88, 102, 186, 208, 87, 101, 78, 111, 189, 5, 144, 101>>
25+
26+
non_string_pointer_key64 = Base.encode64(non_string_pointer_key)
27+
28+
tx_hash = :crypto.strong_rand_bytes(32)
29+
30+
with_mocks [
31+
{AeMdw.Node.Db, [:passthrough],
32+
[
33+
get_tx_data: fn ^tx_hash ->
34+
{:ok, name_hash} = :aens.get_name_hash(name)
35+
36+
{:ok, aetx} =
37+
:aens_update_tx.new(%{
38+
account_id: :aeser_id.create(:account, <<2::256>>),
39+
nonce: 1,
40+
name_id: :aeser_id.create(:name, name_hash),
41+
name_ttl: 1_000,
42+
pointers: [
43+
{:pointer, non_string_pointer_key, pointer_id},
44+
{:pointer, "oracle_pubkey", oracle_id}
45+
],
46+
client_ttl: 1_000,
47+
fee: 5_000
48+
})
49+
50+
{_mod, tx_rec} = :aetx.specialize_type(aetx)
51+
{nil, :name_update_tx, nil, tx_rec}
52+
end
53+
]}
54+
] do
55+
store =
56+
NullStore.new()
57+
|> MemStore.new()
58+
|> Store.put(
59+
Model.Tx,
60+
Model.tx(index: 2, id: tx_hash, block_index: {1, 1})
61+
)
62+
63+
pointers_map = %{
64+
non_string_pointer_key64 => Format.enc_id(pointer_id),
65+
"oracle_pubkey" => Format.enc_id(oracle_id)
66+
}
67+
68+
assert ^pointers_map =
69+
Name.pointers(
70+
State.new(store),
71+
Model.name(
72+
index: name,
73+
updates: [{{1, 1}, 2}]
74+
)
75+
)
76+
end
77+
end
78+
79+
test "encodes custom string pointer key to base64" do
80+
name = "binarypointer.chain"
81+
pointer_id = :aeser_id.create(:account, <<1::256>>)
82+
channel_id = :aeser_id.create(:channel, <<2::256>>)
83+
custom_string_pointer_key = "family_pubkey"
84+
custom_string_pointer_key64 = Base.encode64(custom_string_pointer_key)
85+
86+
tx_hash = :crypto.strong_rand_bytes(32)
87+
88+
with_mocks [
89+
{AeMdw.Node.Db, [:passthrough],
90+
[
91+
get_tx_data: fn ^tx_hash ->
92+
{:ok, name_hash} = :aens.get_name_hash(name)
93+
94+
{:ok, aetx} =
95+
:aens_update_tx.new(%{
96+
account_id: :aeser_id.create(:account, <<2::256>>),
97+
nonce: 1,
98+
name_id: :aeser_id.create(:name, name_hash),
99+
name_ttl: 1_000,
100+
pointers: [
101+
{:pointer, "channel", channel_id},
102+
{:pointer, custom_string_pointer_key, pointer_id}
103+
],
104+
client_ttl: 1_000,
105+
fee: 5_000
106+
})
107+
108+
{_mod, tx_rec} = :aetx.specialize_type(aetx)
109+
{nil, :name_update_tx, nil, tx_rec}
110+
end
111+
]}
112+
] do
113+
store =
114+
NullStore.new()
115+
|> MemStore.new()
116+
|> Store.put(
117+
Model.Tx,
118+
Model.tx(index: 2, id: tx_hash, block_index: {1, 1})
119+
)
120+
121+
pointers_map = %{
122+
custom_string_pointer_key64 => Format.enc_id(pointer_id),
123+
"channel" => Format.enc_id(channel_id)
124+
}
125+
126+
assert ^pointers_map =
127+
Name.pointers(
128+
State.new(store),
129+
Model.name(
130+
index: name,
131+
updates: [{{1, 1}, 2}]
132+
)
133+
)
134+
end
135+
end
136+
end
137+
end

test/ae_mdw_web/controllers/tx_controller_test.exs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule AeMdwWeb.TxControllerTest do
88
alias AeMdw.Node.Db
99
alias AeMdw.TestSamples, as: TS
1010

11-
import AeMdwWeb.BlockchainSim, only: [with_blockchain: 3, tx: 3, name_tx: 3]
11+
import AeMdwWeb.BlockchainSim, only: [with_blockchain: 3, tx: 3, name_tx: 3, name_tx: 4]
1212
import AeMdw.Util.Encoding
1313
import Mock
1414

@@ -299,6 +299,60 @@ defmodule AeMdwWeb.TxControllerTest do
299299
|> json_response(200)
300300
end
301301
end
302+
303+
test "returns a name_update_tx with non-string pointers", %{conn: conn, store: store} do
304+
plain_name = "aliceinchains.chain"
305+
{:ok, name_hash} = :aens.get_name_hash(plain_name)
306+
307+
non_string_pointer_key =
308+
<<104, 65, 117, 174, 49, 251, 29, 202, 69, 174, 147, 56, 60, 150, 188, 247, 149, 85, 150,
309+
148, 88, 102, 186, 208, 87, 101, 78, 111, 189, 5, 144, 101>>
310+
311+
non_string_pointer_key64 = Base.encode64(non_string_pointer_key)
312+
313+
with_blockchain %{alice1: 1_000, alice2: 1_000},
314+
mb: [
315+
tx:
316+
name_tx(:name_update_tx, :alice1, plain_name, %{
317+
pointers: [{:pointer, non_string_pointer_key, :alice2}]
318+
})
319+
] do
320+
%{txs: [tx]} = blocks[:mb]
321+
{:id, :account, alice_pk1} = accounts[:alice1]
322+
{:id, :account, alice_pk2} = accounts[:alice2]
323+
alice_id1 = encode(:account_pubkey, alice_pk1)
324+
alice_id2 = encode(:account_pubkey, alice_pk2)
325+
326+
store =
327+
store
328+
|> Store.put(Model.Tx, Model.tx(index: 1, block_index: {0, 0}, id: :aetx_sign.hash(tx)))
329+
|> Store.put(Model.PlainName, Model.plain_name(index: name_hash, value: plain_name))
330+
|> Store.put(Model.ActiveName, Model.name(index: plain_name))
331+
|> Store.put(Model.Block, Model.block(index: {0, -1}, tx_index: 1))
332+
|> Store.put(Model.Block, Model.block(index: {0, 0}, tx_index: 1))
333+
|> Store.put(Model.Block, Model.block(index: {1, -1}, tx_index: 2))
334+
335+
tx_hash = encode(:tx_hash, :aetx_sign.hash(tx))
336+
337+
assert %{
338+
"hash" => ^tx_hash,
339+
"tx" => %{
340+
"account_id" => ^alice_id1,
341+
"name" => ^plain_name,
342+
"pointers" => [
343+
%{
344+
"id" => ^alice_id2,
345+
"key" => ^non_string_pointer_key64
346+
}
347+
]
348+
}
349+
} =
350+
conn
351+
|> with_store(store)
352+
|> get("/v2/txs/#{tx_hash}")
353+
|> json_response(200)
354+
end
355+
end
302356
end
303357

304358
describe "count" do

test/integration/ae_mdw_web/controllers/name_controller_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,7 @@ defmodule Integration.AeMdwWeb.NameControllerTest do
12411241

12421242
case Name.locate(state, name) do
12431243
{m_name, Model.ActiveName} ->
1244-
Format.map_raw_values(Name.pointers(state, m_name), &Format.to_json/1)
1244+
Name.pointers(state, m_name)
12451245

12461246
{_info, Model.InactiveName} ->
12471247
raise ErrInput.Expired, value: name

test/support/blockchain_sim.ex

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,10 +371,25 @@ defmodule AeMdwWeb.BlockchainSim do
371371
{:id, :account, pubkey} = account_id = Map.fetch!(accounts, account_name)
372372
{:ok, name_hash} = :aens.get_name_hash(plain_name)
373373

374-
pointers = [
375-
{:pointer, "account_pubkey", account_id},
376-
{:pointer, "oracle_pubkey", :aeser_id.create(:oracle, pubkey)}
377-
]
374+
pointers =
375+
case args[:pointers] do
376+
nil ->
377+
[
378+
{:pointer, "account_pubkey", account_id},
379+
{:pointer, "oracle_pubkey", :aeser_id.create(:oracle, pubkey)}
380+
]
381+
382+
list ->
383+
Enum.map(list, fn
384+
{:pointer, key, account_atom} when is_atom(account_atom) ->
385+
{:pointer, key, Map.fetch!(accounts, account_atom)}
386+
387+
another_pointer ->
388+
another_pointer
389+
end)
390+
end
391+
392+
args = Map.delete(args, :pointers)
378393

379394
%{
380395
account_id: account_id,

0 commit comments

Comments
 (0)