Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Data credit support #236

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/blockchain_api/batcher/txns.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ defmodule BlockchainAPI.Batcher.Txns do
to_insert = Transaction.map(:blockchain_txn_payment_v2, txn)
[to_insert | acc]

:blockchain_txn_state_channel_open_v1 ->
to_insert = Transaction.map(:blockchain_txn_state_channel_open_v1, txn)
[to_insert | acc]

:blockchain_txn_state_channel_close_v1 ->
to_insert = Transaction.map(:blockchain_txn_state_channel_close_v1, txn)
[to_insert | acc]

_ ->
acc
end
Expand Down
16 changes: 16 additions & 0 deletions lib/blockchain_api/committer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ defmodule BlockchainAPI.Committer do
Schema.OUITransaction,
Schema.SecurityExchangeTransaction,
Schema.PaymentV2Txn,
Schema.StateChannelOpenTxn,
Schema.StateChannelCloseTxn,
Notifier
}

Expand Down Expand Up @@ -266,6 +268,12 @@ defmodule BlockchainAPI.Committer do
:blockchain_txn_oui_v1 ->
insert_transaction(:blockchain_txn_oui_v1, txn, height)

:blockchain_txn_state_channel_open_v1 ->
insert_transaction(:blockchain_txn_state_channel_open_v1, txn, height)

:blockchain_txn_state_channel_close_v1 ->
insert_transaction(:blockchain_txn_state_channel_close_v1, txn, height)

:blockchain_txn_payment_v2 ->
insert_transaction(:blockchain_txn_payment_v2, txn, height)

Expand Down Expand Up @@ -423,6 +431,13 @@ defmodule BlockchainAPI.Committer do
{:ok, _} = Query.PaymentV2Txn.create(cs)
end

defp insert_transaction(:blockchain_txn_state_channel_open_v1, txn, _height) do
{:ok, _} = Query.StateChannelOpenTxn.create(StateChannelOpenTxn.map(txn))
end

defp insert_transaction(:blockchain_txn_state_channel_close_v1, txn, _height) do
{:ok, _} = Query.StateChannelCloseTxn.create(StateChannelCloseTxn.map(txn))
end

defp insert_transaction(:blockchain_txn_consensus_group_v1, txn, height, time) do
{:ok, election_entry} = Query.ElectionTransaction.create(ElectionTransaction.map(txn))
Expand Down Expand Up @@ -534,6 +549,7 @@ defmodule BlockchainAPI.Committer do
Batcher.Pocs.insert_receipt_and_witnesses(txn, block, ledger, height, poc_receipt_txn_entry)
end


# ==================================================================
# Insert account transactions
# ==================================================================
Expand Down
18 changes: 18 additions & 0 deletions lib/blockchain_api/query/state_channel_close_txn.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule BlockchainAPI.Query.StateChannelCloseTxn do
@moduledoc false
import Ecto.Query, warn: false

alias BlockchainAPI.{Repo, Schema.StateChannelCloseTxn}

def create(attrs \\ %{}) do
%StateChannelCloseTxn{}
|> StateChannelCloseTxn.changeset(attrs)
|> Repo.insert()
end

def get!(hash) do
StateChannelCloseTxn
|> where([scc], scc.hash == ^hash)
|> Repo.replica.one!()
end
end
18 changes: 18 additions & 0 deletions lib/blockchain_api/query/state_channel_open_txn.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule BlockchainAPI.Query.StateChannelOpenTxn do
@moduledoc false
import Ecto.Query, warn: false

alias BlockchainAPI.{Repo, Schema.StateChannelOpenTxn}

def create(attrs \\ %{}) do
%StateChannelOpenTxn{}
|> StateChannelOpenTxn.changeset(attrs)
|> Repo.insert()
end

def get!(hash) do
StateChannelOpenTxn
|> where([sco], sco.hash == ^hash)
|> Repo.replica.one!()
end
end
10 changes: 9 additions & 1 deletion lib/blockchain_api/query/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ defmodule BlockchainAPI.Query.Transaction do
Schema.OUITransaction,
Schema.SecurityExchangeTransaction,
Schema.PaymentV2Txn,
Schema.StateChannelOpenTxn,
Schema.StateChannelCloseTxn,
Util
}

Expand Down Expand Up @@ -310,6 +312,10 @@ defmodule BlockchainAPI.Query.Transaction do
on: transaction.hash == sec_exchange_txn.hash,
left_join: payment_v2 in PaymentV2Txn,
on: transaction.hash == payment_v2.hash,
left_join: sc_open_txn in StateChannelOpenTxn,
on: transaction.hash == sc_open_txn.hash,
left_join: sc_close_txn in StateChannelCloseTxn,
on: transaction.hash == sc_close_txn.hash,
order_by: [
desc: block.height,
desc: transaction.id,
Expand All @@ -331,7 +337,9 @@ defmodule BlockchainAPI.Query.Transaction do
rewards: rewards_txn,
oui: oui_txn,
sec_exchange: sec_exchange_txn,
payment_v2: payment_v2
payment_v2: payment_v2,
sc_open: sc_open_txn,
sc_close: sc_close_txn
}
)

Expand Down
122 changes: 122 additions & 0 deletions lib/blockchain_api/schema/state_channel_close.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
defmodule BlockchainAPI.Schema.StateChannel do
use Ecto.Schema
import Ecto.Changeset

@fields [:id, :owner, :credits, :nonce, :summaries, :root_hash, :state, :expire_at_block]

@derive {Jason.Encoder, only: @fields}
@primary_key false
embedded_schema do
field :id, :string, null: false
field :owner, :string, null: false
field :nonce, :integer, null: false
embeds_many :summaries, BlockchainAPI.Schema.StateChannel.Summary
field :root_hash, :string
field :state, :string, null: false
field :expire_at_block, :integer
end

def changeset(schema, params) do
schema
|> cast(params, [:id, :owner, :nonce, :root_hash, :state, :expire_at_block])
|> cast_embed(:summaries)
end

end

defmodule BlockchainAPI.Schema.StateChannel.Summary do
use Ecto.Schema
import Ecto.Changeset

@fields [:client, :num_dcs, :num_packets]

@derive {Jason.Encoder, only: @fields}
@primary_key false
schema "summaries" do
field :client, :string
field :num_packets, :integer
field :num_dcs, :integer
end

def changeset(schema, params) do
schema
|> cast(params, [:client, :num_packets, :num_dcs])
end

end

defmodule BlockchainAPI.Schema.StateChannelCloseTxn do
use Ecto.Schema
import Ecto.Changeset
alias BlockchainAPI.{Util, Schema.StateChannelCloseTxn}

@fields [:closer, :state_channel]

@derive {Phoenix.Param, key: :hash}
@derive {Jason.Encoder, only: @fields}
schema "state_channel_close_transactions" do
field :closer, :binary, null: false
field :hash, :binary, null: false
embeds_one :state_channel, BlockchainAPI.Schema.StateChannel

timestamps()
end

@doc false
def changeset(txn, attrs) do
txn
|> cast(attrs, [:closer, :hash])
|> cast_embed(:state_channel)
|> validate_required([:closer, :state_channel])
|> foreign_key_constraint(:hash)
end

def encode_model(state_channel_close_transaction) do
state_channel_close_transaction
|> Map.take(@fields)
|> Map.merge(%{
closer: Util.bin_to_string(state_channel_close_transaction.closer),
type: "sc_close"
})
end

defimpl Jason.Encoder, for: StateChannelCloseTxn do
def encode(txn, opts) do
txn
|> StateChannelCloseTxn.encode_model()
|> Jason.Encode.map(opts)
end
end

def map(txn) do

sc0 = :blockchain_txn_state_channel_close_v1.state_channel(txn)

summaries = sc0
|> :blockchain_state_channel_v1.summaries()
|> Enum.map(
fn(summary) ->
client = :blockchain_state_channel_summary_v1.client_pubkeybin(summary)
num_packets = :blockchain_state_channel_summary_v1.num_packets(summary)
num_dcs = :blockchain_state_channel_summary_v1.num_dcs(summary)
%{client: Util.bin_to_string(client), num_dcs: num_dcs, num_packets: num_packets}
end)

sc = %{
id: Util.bin_to_string(:blockchain_state_channel_v1.id(sc0)),
owner: Util.bin_to_string(:blockchain_state_channel_v1.owner(sc0)),
nonce: :blockchain_state_channel_v1.nonce(sc0),
summaries: summaries,
root_hash: Util.bin_to_string(:blockchain_state_channel_v1.root_hash(sc0)),
state: Atom.to_string(:blockchain_state_channel_v1.state(sc0)),
expire_at_block: :blockchain_state_channel_v1.expire_at_block(sc0)
}

%{
closer: :blockchain_txn_state_channel_close_v1.closer(txn),
hash: :blockchain_txn_state_channel_close_v1.hash(txn),
state_channel: sc
}
end

end
59 changes: 59 additions & 0 deletions lib/blockchain_api/schema/state_channel_open_txn.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
defmodule BlockchainAPI.Schema.StateChannelOpenTxn do
use Ecto.Schema
import Ecto.Changeset
alias BlockchainAPI.{Util, Schema.StateChannelOpenTxn}

@fields [:id, :owner, :oui, :expire_within, :height, :time]

@primary_key false
@derive {Phoenix.Param, key: :hash}
@derive {Jason.Encoder, only: @fields}
schema "state_channel_open_transactions" do
field :id, :binary, null: false, primary_key: true
field :hash, :binary, null: false
field :oui, :integer, null: false
field :owner, :binary, null: false
field :nonce, :integer, null: false
field :expire_within, :integer, null: false

timestamps()
end

@doc false
def changeset(txn, attrs) do
txn
|> cast(attrs, [:id, :hash, :oui, :owner, :nonce, :expire_within])
|> validate_required([:id, :hash, :oui, :owner, :nonce, :expire_within])
|> foreign_key_constraint(:hash)
end

def encode_model(state_channel_open_transaction) do
state_channel_open_transaction
|> Map.take(@fields)
|> Map.merge(%{
id: Util.bin_to_string(state_channel_open_transaction.id),
owner: Util.bin_to_string(state_channel_open_transaction.owner),
hash: Util.bin_to_string(state_channel_open_transaction.hash),
type: "sc_open"
})
end

defimpl Jason.Encoder, for: StateChannelOpenTxn do
def encode(txn, opts) do
txn
|> StateChannelOpenTxn.encode_model()
|> Jason.Encode.map(opts)
end
end

def map(txn) do
%{
id: :blockchain_txn_state_channel_open_v1.id(txn),
owner: :blockchain_txn_state_channel_open_v1.owner(txn),
oui: :blockchain_txn_state_channel_open_v1.oui(txn),
nonce: :blockchain_txn_state_channel_open_v1.nonce(txn),
expire_within: :blockchain_txn_state_channel_open_v1.expire_within(txn),
hash: :blockchain_txn_state_channel_open_v1.hash(txn)
}
end
end
8 changes: 8 additions & 0 deletions lib/blockchain_api/schema/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,12 @@ defmodule BlockchainAPI.Schema.Transaction do
def map(:blockchain_txn_payment_v2, txn) do
%{type: "payment_v2", hash: :blockchain_txn_payment_v2.hash(txn)}
end

def map(:blockchain_txn_state_channel_open_v1, txn) do
%{type: "sc_open", hash: :blockchain_txn_state_channel_open_v1.hash(txn)}
end

def map(:blockchain_txn_state_channel_close_v1, txn) do
%{type: "sc_close", hash: :blockchain_txn_state_channel_close_v1.hash(txn)}
end
end
20 changes: 19 additions & 1 deletion lib/blockchain_api/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ defmodule BlockchainAPI.Util do
SecurityTransaction,
OUITransaction,
SecurityExchangeTransaction,
PaymentV2Txn
PaymentV2Txn,
StateChannelOpenTxn,
StateChannelCloseTxn
}

@bones 100_000_000
Expand Down Expand Up @@ -206,6 +208,22 @@ defmodule BlockchainAPI.Util do
})
end

def clean_txn_struct(%{sc_open: sc_open, height: height, time: time}) when is_map(sc_open) do
Map.merge(StateChannelOpenTxn.encode_model(sc_open), %{
type: "sc_open",
height: height,
time: time
})
end

def clean_txn_struct(%{sc_close: sc_close, height: height, time: time}) when is_map(sc_close) do
Map.merge(StateChannelCloseTxn.encode_model(sc_close), %{
type: "sc_close",
height: height,
time: time
})
end

def clean_txn_struct(%{height: _height, time: _time}), do: nil
def clean_txn_struct(map) when map == %{}, do: nil

Expand Down
18 changes: 17 additions & 1 deletion lib/blockchain_api_web/controllers/transaction_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ defmodule BlockchainAPIWeb.TransactionController do
RewardsView,
OUIView,
SecExchangeView,
PaymentV2View
PaymentV2View,
StateChannelOpenView,
StateChannelCloseView
}

import BlockchainAPI.Cache.CacheService
Expand Down Expand Up @@ -128,6 +130,20 @@ defmodule BlockchainAPIWeb.TransactionController do
|> put_view(PaymentV2View)
|> render("show.json", payment_v2: payment_v2)

"sc_open" ->
sc_open = Query.StateChannelOpenTxn.get!(bin_hash)

conn
|> put_view(StateChannelOpenView)
|> render("show.json", sc_open: sc_open)

"sc_close" ->
sc_close = Query.StateChannelCloseTxn.get!(bin_hash)

conn
|> put_view(StateChannelCloseView)
|> render("show.json", sc_close: sc_close)

_ ->
:error
end
Expand Down
Loading