Skip to content

Commit

Permalink
more setup
Browse files Browse the repository at this point in the history
  • Loading branch information
SachinMeier committed Mar 17, 2023
1 parent 201184a commit efa12e2
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 37 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ bao-*.tar
npm-debug.log
/assets/node_modules/

.DS_Store
.DS_Store

**/*.secret.exs
2 changes: 2 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,5 @@ config :phoenix, :stacktrace_depth, 20

# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime

import_config "dev.secret.exs"
18 changes: 18 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '3'

services:
bao_postgres:
image: postgres:12.10
container_name: bao_postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- bao-postgres-volume:/var/lib/postgresql/data
restart: on-failure
ports:
- "5438:5432"

volumes:
bao-postgres-volume:
21 changes: 21 additions & 0 deletions lib/bao.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,25 @@ defmodule Bao do
Contexts are also responsible for managing your data, regardless
if it comes from the database, an external API or others.
"""

alias Bitcoinex.Secp256k1.PrivateKey

# point = get_point()

# scalar = get_scalar()

# TODO get once from env and store in memory
def get_scalar() do
{:ok, privkey} =
Application.fetch_env!(:bao, :private_key)
|> Base.decode16!(case: :lower)
|> :binary.decode_unsigned()
|> PrivateKey.new()
privkey
end

def get_point() do
{:ok, point} = PrivateKey.to_point(get_scalar())
point
end
end
40 changes: 25 additions & 15 deletions lib/bao/events.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ defmodule Bao.Events do

alias Bao.Events.Event

@doc """
Returns the list of events.
alias Bitcoinex.Secp256k1

## Examples
# @doc """
# Returns the list of events.

iex> list_events()
[%Event{}, ...]
# ## Examples

"""
def list_events do
Repo.all(Event)
end
# iex> list_events()
# [%Event{}, ...]

# """
# def list_events do
# Repo.all(Event)
# end

@doc """
Gets a single event.
Expand All @@ -35,10 +37,10 @@ defmodule Bao.Events do
** (Ecto.NoResultsError)
"""
def get_event!(id), do: Repo.get!(Event, id)
# def get_event!(id), do: Repo.get!(Event, id)

def get_event_by_point!(point) do
# TODO
def get_event_pubkey_by_point!(point) do
Repo.get_by(EventPubkey, [point: point])
end

@doc """
Expand All @@ -53,12 +55,10 @@ defmodule Bao.Events do
{:error, %Ecto.Changeset{}}
"""
def create_event(attrs \\ %{}) do
def create_event(attrs) do
# create all pubkey entries
# put len(pubkeys) in attrs
# generate new event


%Event{}
|> Event.changeset(attrs)
|> Repo.insert()
Expand Down Expand Up @@ -206,4 +206,14 @@ defmodule Bao.Events do
def change_event_pubkey(%EventPubkey{} = event_pubkey, attrs \\ %{}) do
EventPubkey.changeset(event_pubkey, attrs)
end

def verify_event_signature(event_point, user_point, signature) do
sighash =
event_point
|> Base.decode16!( case: :lower)
|> :binary.decode_unsigned()
{:ok, user_pk} = Secp256k1.Point.lift_x(user_point)
{:ok, sig} = Secp256k1.Signature.parse_signature(signature)
Secp256k1.Schnorr.verify_signature(user_pk, sighash, sig)
end
end
37 changes: 26 additions & 11 deletions lib/bao/events/event.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,67 @@ defmodule Bao.Events.Event do
use Ecto.Schema
import Ecto.Changeset

alias Bao.Events.EventPubkey
alias Bao

alias Bitcoinex.Script
alias Bitcoinex.Utils, as: BtcUtils
alias Bitcoinex.Secp256k1

@bao_scalar Bao.get_scalar().d

schema "events" do
field :point, :string
field :pubkey_ct, :integer
field :point, :string
field :scalar, :string
field :state, :string
has_many :event_pubkeys, EventPubkey

timestamps()
end

@doc false
def changeset(event, attrs = %{"pubkeys" => pubkeys}) do
attrs = Map.put(attrs, "pubkey_ct", length(pubkeys))
attrs =
attrs
|> Map.put("pubkey_ct", length(pubkeys))
|> Map.put("point", calculate_event_point(pubkeys))

event
|> cast(attrs, [:pubkey_ct, :state, :point, :scalar])
|> validate_required([:pubkey_ct, :state, :point, :scalar])
|> cast(attrs, [:pubkey_ct, :point])
|> validate_required([:pubkey_ct, :point])
|> validate_length(:point, is: 33)
|> validate_length(:scalar, is: 32)
|> validate_number(:pubkey_ct, greater_than: 0)
end

defp calculate_event_hash(pubkeys) do
def calculate_event_hash(pubkeys) do
# sort pubkeys, concatenate them, hash them, convert to point
{:ok, scalar} =
pubkeys
|> Enum.map(fn pk -> {:ok, point} = Secp256k1.Point.lift_x(pk); point end)
|> Script.lexicographical_sort_pubkeys()
|> Enum.reduce(<<>>, fn pk, acc -> acc <> Secp256k1.Point.x_bytes(pk) end)
|> BtcUtils.double_sha256()
|> :binary.decode_unsigned()
|> Secp256k1.PrivateKey.new()
scalar
end

defp calculate_event_scalar(%Secp256k1.PrivateKey{d: bao_scalar}, pubkeys) do
def calculate_event_scalar(pubkeys) do
# the event_scalar is just the event_hash tweaked with the Bao's scalar
event_hash = calculate_event_hash(pubkeys)
PrivateKey.new(event_hash + bao_scalar)
{:ok, scalar} = PrivateKey.new(event_hash + @bao_scalar)
Secp256k1.force_even_y(scalar)
end

defp calculate_event_point(bao_point, pubkeys) do
def calculate_event_point(pubkeys) do
# TODO don't recalc this every time
bao_point = Secp256k1.PrivateKey.to_point(@bao_scalar)
event_hash = calculate_event_hash(pubkeys)
{:ok, point} = Secp256k1.PrivateKey.to_point(event_hash)
point = Secp256k1.PrivateKey.to_point(event_hash)
# tweak event_hash_point with bao pubkey
Secp256k1.Math.add(point, bao_point)
# force even
|> Secp256k1.Point.x_bytes()
|> Secp256k1.Point.lift_x()
end
end
2 changes: 1 addition & 1 deletion lib/bao/events/event_pubkey.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Bao.Events.EventPubkey do
field :signature, :string
field :signed, :boolean, default: false
field :signed_at, :utc_datetime
field :event_id, :id
belongs_to :event, Event

timestamps()
end
Expand Down
1 change: 1 addition & 0 deletions lib/bao/mailer.ex
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
defmodule Bao.Mailer do
use Swoosh.Mailer, otp_app: :bao
# TODO: delete
end
13 changes: 8 additions & 5 deletions lib/bao_web/controllers/event_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ defmodule BaoWeb.EventController do
# render(conn, "index.json", events: events)
# end

def create(conn, %{"event" => event_params}) do
def create(conn, attrs = %{"pubkeys" => pubkeys}) do
# TODO: Just return pubkeys & event_point
with {:ok, %Event{} = event} <- Events.create_event(event_params) do
with {:ok, %Event{} = event} <- Events.create_event(attrs) do
conn
|> put_status(:created)
|> put_resp_header("location", Routes.event_path(conn, :show, event))
Expand All @@ -27,10 +27,13 @@ defmodule BaoWeb.EventController do
render(conn, "show.json", event: event)
end

def update(conn, %{"point" => point, "signature" => signature}) do
event = Events.get_event_by_point!(point)
def update(conn, %{"point" => user_point, "signature" => signature}) do
event = Events.get_event_by_point!(user_point)

# TODO error if this fails
true = Events.verify_event_signature(event.point, user_point, signature)

event_pk = Events.get_event_pubkey!(point)
event_pk = Events.get_event_pubkey!(user_point)

with {:ok, _} <- EventPubkeys.update_event_pubkey(event_pk, %{"signature" => signature}) do
# If successfully verified sig
Expand Down
2 changes: 1 addition & 1 deletion lib/bao_web/router.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule BaoWeb.Router do
alias BaoWeb.EventController
# alias BaoWeb.EventController
use BaoWeb, :router

pipeline :api do
Expand Down
1 change: 0 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ defmodule Bao.MixProject do
version: "0.1.0",
elixir: "~> 1.12",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:gettext] ++ Mix.compilers(),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps()
Expand Down
1 change: 0 additions & 1 deletion priv/repo/migrations/20230316225510_create_events.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ defmodule Bao.Repo.Migrations.CreateEvents do
def change do
create table(:events) do
add :pubkey_ct, :integer
add :state, :string
add :point, :string
add :scalar, :string

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ defmodule Bao.Repo.Migrations.CreateEventPubkeys do
add :pubkey, :string
add :signed, :boolean, default: false, null: false
add :signature, :string
add :signed_at, :utc_datetime
add :event_id, references(:events, on_delete: :nothing)

timestamps()
end

# TODO create index(:events_event_pubkeys, [:pubkey, :event_id])
create index(:event_pubkeys, [:event_id])
end
end

0 comments on commit efa12e2

Please sign in to comment.