Skip to content

Commit

Permalink
get transaction api batch
Browse files Browse the repository at this point in the history
  • Loading branch information
InoMurko committed Feb 24, 2021
1 parent fbed2fc commit 1fcc7dc
Show file tree
Hide file tree
Showing 21 changed files with 358 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "priv/cabbage"]
path = priv/cabbage
url = https://github.com/omgnetwork/specs.git
branch = master
branch = inomurko/batch_through_watcher
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ start-watcher:
rm -f ./_build/${BAREBUILD_ENV}/rel/watcher/var/sys.config || true && \
echo "Init Watcher DBs" && \
_build/${BAREBUILD_ENV}/rel/watcher/bin/watcher eval "OMG.DB.ReleaseTasks.InitKeyValueDB.run()" && \
_build/${BAREBUILD_ENV}/rel/watcher_info/bin/watcher_info eval "OMG.DB.ReleaseTasks.InitKeysWithValues.run()" && \
_build/${BAREBUILD_ENV}/rel/watcher/bin/watcher eval "OMG.DB.ReleaseTasks.InitKeysWithValues.run()" && \
echo "Run Watcher" && \
. ${OVERRIDING_VARIABLES} && \
PORT=${WATCHER_PORT} _build/${BAREBUILD_ENV}/rel/watcher/bin/watcher $(OVERRIDING_START)
Expand Down
2 changes: 1 addition & 1 deletion apps/omg_utils/lib/omg_utils/http_rpc/response.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ defmodule OMG.Utils.HttpRPC.Response do
end

def sanitize(list) when is_list(list) do
list |> Enum.map(&sanitize/1)
Enum.map(list, &sanitize/1)
end

def sanitize(map_or_struct) when is_map(map_or_struct) do
Expand Down
9 changes: 9 additions & 0 deletions apps/omg_watcher/lib/omg_watcher/api/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ defmodule OMG.Watcher.API.Transaction do
* transaction doesn't spend funds not yet mined
* etc...
"""
@spec submit(list(Transaction.Signed.t())) :: Client.response_t() | {:error, atom()}
def batch_submit(signed_txs) do
url = Application.get_env(:omg_watcher, :child_chain_url)

signed_txs
|> Enum.map(&Transaction.Signed.encode(&1))
|> Client.batch_submit(url)
end

@spec submit(Transaction.Signed.t()) :: Client.response_t() | {:error, atom()}
def submit(%Transaction.Signed{} = signed_tx) do
url = Application.get_env(:omg_watcher, :child_chain_url)
Expand Down
32 changes: 30 additions & 2 deletions apps/omg_watcher/lib/omg_watcher/http_rpc/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,17 @@ defmodule OMG.Watcher.HttpRPC.Client do
@spec submit(binary(), binary()) :: response_t()
def submit(tx, url), do: call(%{transaction: Encoding.to_hex(tx)}, "transaction.submit", url)

defp call(params, path, url),
do: Adapter.rpc_post(params, path, url) |> Adapter.get_response_body() |> decode_response()
@doc """
Submits a batch of transactions
"""
@spec batch_submit(binary(), binary()) :: response_t()
def batch_submit(txs, url) do
call(%{transactions: Enum.map(txs, &Encoding.to_hex(&1))}, "transaction.batch_submit", url)
end

defp call(params, path, url) do
params |> Adapter.rpc_post(path, url) |> Adapter.get_response_body() |> decode_response()
end

# Translates response's body to known elixir structure, either block or tx submission response or error.
defp decode_response({:ok, %{transactions: transactions, blknum: number, hash: hash}}) do
Expand All @@ -57,8 +66,27 @@ defmodule OMG.Watcher.HttpRPC.Client do
{:ok, Map.update!(response, :txhash, &decode16!/1)}
end

defp decode_response({:ok, response}) when is_list(response) do
decode_response(response, [])
# defp decode_response({:ok, [%{txhash: _hash} = transaction_response |response]}) do
# Map.update!(transaction_response, :txhash, &decode16!/1)
end

defp decode_response(error), do: error

defp decode_response([], acc) do
Enum.reverse(acc)
end

defp decode_response([%{txhash: _hash} = transaction_response | response], acc) do
decode_response(response, [Map.update!(transaction_response, :txhash, &decode16!/1) | acc])
end

# all error tuples
defp decode_response([transaction_response | response], acc) do
decode_response(response, [transaction_response | acc])
end

defp decode16!(hexstr) do
{:ok, bin} = Encoding.from_hex(hexstr)
bin
Expand Down
40 changes: 40 additions & 0 deletions apps/omg_watcher_rpc/lib/web/controllers/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ defmodule OMG.WatcherRPC.Web.Controller.Transaction do
end
end

@doc """
Submits transaction to child chain
"""
def batch_submit(conn, params) do
with {:ok, txbytes} <- expect(params, "transactions", list: &to_transaction/1, optional: false) do
submit_tx_sec(txbytes, conn)
end
end

@doc """
Thin-client version of `/transaction.submit` that accepts json encoded transaction
"""
Expand Down Expand Up @@ -109,6 +118,18 @@ defmodule OMG.WatcherRPC.Web.Controller.Transaction do
end

# Provides extra validation (recover_from) and passes transaction to API layer
defp submit_tx_sec(txbytes, conn) when is_list(txbytes) do
case recover(txbytes) do
recovered when is_list(recovered) ->
recovered
|> SecurityApiTransaction.batch_submit()
|> api_response(conn, :batch_submission)

other ->
other
end
end

defp submit_tx_sec(txbytes, conn) do
with {:ok, recovered_tx} <- Transaction.Recovered.recover_from(txbytes),
:ok <- is_supported(recovered_tx) do
Expand All @@ -125,4 +146,23 @@ defmodule OMG.WatcherRPC.Web.Controller.Transaction do
do: {:error, :transaction_not_supported}

defp is_supported(%Transaction.Recovered{}), do: :ok

defp to_transaction(transaction) do
expect(%{"transaction" => transaction}, "transaction", :hex)
end

defp recover(transactions) do
recover(transactions, [])
end

defp recover([], acc) do
acc
end

defp recover([txbytes | transactions], acc) do
with {:ok, recovered_tx} <- Transaction.Recovered.recover_from(txbytes),
:ok <- is_supported(recovered_tx) do
recover(transactions, [Map.get(recovered_tx, :signed_tx) | acc])
end
end
end
2 changes: 2 additions & 0 deletions apps/omg_watcher_rpc/lib/web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ defmodule OMG.WatcherRPC.Web.Router do
post("/utxo.get_challenge_data", Controller.Challenge, :get_utxo_challenge)

post("/transaction.submit", Controller.Transaction, :submit)
post("/transaction.batch_submit", Controller.Transaction, :batch_submit)

post("/in_flight_exit.get_data", Controller.InFlightExit, :get_in_flight_exit)
post("/in_flight_exit.get_competitor", Controller.InFlightExit, :get_competitor)
Expand All @@ -83,6 +84,7 @@ defmodule OMG.WatcherRPC.Web.Router do
post("/transaction.all", Controller.Transaction, :get_transactions)
post("/transaction.get", Controller.Transaction, :get_transaction)
post("/transaction.create", Controller.Transaction, :create)

post("/transaction.submit_typed", Controller.Transaction, :submit_typed)
post("/transaction.merge", Controller.Transaction, :merge)

Expand Down
6 changes: 6 additions & 0 deletions apps/omg_watcher_rpc/lib/web/views/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ defmodule OMG.WatcherRPC.Web.View.Transaction do
|> WatcherRPCResponse.add_app_infos()
end

def render("batch_submission.json", %{response: transactions}) do
transactions
|> Response.serialize()
|> WatcherRPCResponse.add_app_infos()
end

def render("merge.json", %{response: advice}) do
render_transactions(advice)
end
Expand Down
7 changes: 0 additions & 7 deletions apps/omg_watcher_rpc/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@ defmodule OMG.WatcherRPC.Mixfile do
use Mix.Project

def project() do
version =
"git"
|> System.cmd(["describe", "--tags", "--abbrev=0"])
|> elem(0)
|> String.replace("v", "")
|> String.replace("\n", "")

[
app: :omg_watcher_rpc,
version: version(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
transaction.batch_submit:
post:
tags:
- Transaction
summary: This endpoint submits an array of signed transaction to the child chain.
description: >
Normally you should call the Watcher's Transaction - Submit instead of this.
The Watcher's version performs various security and validation checks (TO DO) before submitting the transaction,
so is much safer. However, if the Watcher is not available this version exists.
operationId: batch_submit
requestBody:
$ref: 'request_bodies.yaml#/TransactionBatchSubmitBodySchema'
responses:
200:
$ref: 'responses.yaml#/TransactionBatchSubmitResponse'
500:
$ref: '../responses.yaml#/InternalServerError'
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
TransactionBatchSubmitBodySchema:
description: Array of signed transactions, RLP-encoded to bytes, and HEX-encoded to string
required: true
content:
application/json:
schema:
title: 'TransactionBatchSubmitBodySchema'
type: object
properties:
transactions:
type: array
items:
type: string
required:
- transactions
example:
transactions: ['0xf8d083015ba98080808080940000...', '0xf8d083a15ba98080808080920000...']
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
TransactionBatchSubmitResponseSchema:
allOf:
- $ref: '../response_schemas.yaml#/WatcherBaseResponseSchema'
- type: object
properties:
data:
type: array
$ref: 'schemas.yaml#/TransactionBatchSubmitSchema '
example:
data:
-
blknum: 123000
txindex: 111
txhash: '0xbdf562c24ace032176e27621073df58ce1c6f65de3b5932343b70ba03c72132d'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TransactionBatchSubmitResponse:
description: Transaction batch submission successful response
content:
application/json:
schema:
$ref: 'response_schemas.yaml#/TransactionBatchSubmitResponseSchema'
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
TransactionBatchSubmitSchema:
type: array
items:
type: object
properties:
blknum:
type: integer
format: int64
txindex:
type: integer
format: int16
txhash:
type: string

0 comments on commit 1fcc7dc

Please sign in to comment.