Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename #31

Merged
merged 3 commits into from
Mar 1, 2024
Merged
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ erl_crash.dump
*.ez

# Ignore package tarball (built via "mix hex.build").
hexpds-*.tar
hipdster-*.tar

# Temporary files, for example, from tests.
/tmp/
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# hexpds
# hipdster
An ATProto PDS in Elixir/Rust

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `hexpds` to your list of dependencies in `mix.exs`:
by adding `hipdster` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:hexpds, "~> 0.1.0"}
{:hipdster, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/hexpds>.
be found at <https://hexdocs.pm/hipdster>.

4 changes: 2 additions & 2 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Config

# example usage:
#  Application.get_env(:hexpds, :plc_server)
#  Application.get_env(:hipdster, :plc_server)

config :hexpds,
config :hipdster,
plc_server: "plc.bsky-sandbox.dev",
appview_server: "api.bsky-sandbox.dev",
relay_server: "bgs.bsky-sandbox.dev",
Expand Down
Empty file removed lib/hexpds/mst.ex
Empty file.
4 changes: 2 additions & 2 deletions lib/hexpds/cid.ex → lib/hipdster/cid.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Hexpds.CID do
defmodule Hipdster.CID do
@moduledoc """
CID - self-describing content-addressed identifiers for distributed systems.

Expand Down Expand Up @@ -96,7 +96,7 @@ defmodule Hexpds.CID do

"""

alias Hexpds.Multicodec, as: Multicodec
alias Hipdster.Multicodec, as: Multicodec

alias __MODULE__, as: CID

Expand Down
6 changes: 3 additions & 3 deletions lib/hexpds/dagcbor.ex → lib/hipdster/dagcbor.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Hexpds.DagCBOR do
defmodule Hipdster.DagCBOR do
defmodule Internal do
use Rustler, otp_app: :hexpds, crate: "hexpds_dagcbor_internal"
use Rustler, otp_app: :hipdster, crate: "hipdster_dagcbor_internal"
@spec encode_dag_cbor(binary()) :: {:ok, binary()} | {:error, String.t()}
def encode_dag_cbor(_json), do: :erlang.nif_error(:nif_not_loaded)
@spec decode_dag_cbor(binary()) :: {:ok, String.t()} | {:error, String.t()}
Expand All @@ -13,7 +13,7 @@ defmodule Hexpds.DagCBOR do

Examples:

iex> Hexpds.DagCBOR.encode(%{apple: "banana", cranberry: "dragonfruit"})
iex> Hipdster.DagCBOR.encode(%{apple: "banana", cranberry: "dragonfruit"})
...> |> elem(1)
...> |> Base.encode16()
"A2656170706C656662616E616E61696372616E62657272796B647261676F6E6672756974"
Expand Down
14 changes: 7 additions & 7 deletions lib/hexpds/didgenerator.ex → lib/hipdster/didgenerator.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Hexpds.DidGenerator do
defmodule Hipdster.DidGenerator do
require Logger
alias Hexpds.K256, as: K256
alias Hipdster.K256, as: K256

@spec genesis_to_did(map()) :: String.t()
def genesis_to_did(%{"type" => "plc_operation", "prev" => nil} = signed_genesis) do
Expand All @@ -10,7 +10,7 @@ defmodule Hexpds.DidGenerator do
|> Jason.encode(),
{:ok, signed_genesis_cbor} <-
signed_genesis_json
|> Hexpds.DagCBOR.encode(),
|> Hipdster.DagCBOR.encode(),
do:
:crypto.hash(:sha256, signed_genesis_cbor)
|> Base.encode32(case: :lower)
Expand Down Expand Up @@ -55,24 +55,24 @@ defmodule Hexpds.DidGenerator do

def generate_did(
"" <> handle,
"" <> plc_dir_url \\ "https://#{Application.get_env(:hexpds, :plc_server)}",
"" <> pds_url \\ Application.get_env(:hexpds, :pds_host)
"" <> plc_dir_url \\ "https://#{Application.get_env(:hipdster, :plc_server)}",
"" <> pds_url \\ Application.get_env(:hipdster, :pds_host)
) do
rotation_key = K256.PrivateKey.create()
signing_key = K256.PrivateKey.create()
Logger.info("Rotation key: #{rotation_key |> K256.PrivateKey.to_hex()}")
Logger.info("Signing key: #{signing_key |> K256.PrivateKey.to_hex()}")

genesis =
Hexpds.DidPlc.Operation.genesis(
Hipdster.DidPlc.Operation.genesis(
rotation_key,
signing_key,
handle,
pds_url
)

Logger.info("Genesis: #{inspect(genesis)}")
signed_genesis = Hexpds.DidPlc.Operation.add_sig(genesis, rotation_key)
signed_genesis = Hipdster.DidPlc.Operation.add_sig(genesis, rotation_key)
did = genesis_to_did(signed_genesis)
Logger.info("DID: #{did}")

Expand Down
29 changes: 14 additions & 15 deletions lib/hexpds/didplc.ex → lib/hipdster/didplc.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Hexpds.DidPlc do
defmodule Hipdster.DidPlc do
defmodule Operation do
defstruct [
:rotationKeys,
Expand All @@ -10,7 +10,7 @@ defmodule Hexpds.DidPlc do
]

@type t :: %__MODULE__{
rotationKeys: [Hexpds.K256.PrivateKey.t()],
rotationKeys: [Hipdster.K256.PrivateKey.t()],
prev: String.t() | nil,
verificationMethods: VerificationMethods.t(),
alsoKnownAs: [String.t()],
Expand All @@ -20,7 +20,7 @@ defmodule Hexpds.DidPlc do

defmodule VerificationMethods do
defstruct([:atproto])
@type t :: %__MODULE__{atproto: Hexpds.K256.PrivateKey.t()}
@type t :: %__MODULE__{atproto: Hipdster.K256.PrivateKey.t()}
end

defmodule Services do
Expand All @@ -36,8 +36,8 @@ defmodule Hexpds.DidPlc do
end

def genesis(
%Hexpds.K256.PrivateKey{} = rotationkey,
%Hexpds.K256.PrivateKey{} = signingkey,
%Hipdster.K256.PrivateKey{} = rotationkey,
%Hipdster.K256.PrivateKey{} = signingkey,
handle,
pds
) do
Expand All @@ -52,7 +52,7 @@ defmodule Hexpds.DidPlc do

def to_json(%__MODULE__{} = operation) do
encodekeys = fn k ->
k |> Hexpds.K256.PrivateKey.to_pubkey() |> Hexpds.K256.PublicKey.to_did_key()
k |> Hipdster.K256.PrivateKey.to_pubkey() |> Hipdster.K256.PublicKey.to_did_key()
end

Jason.encode!(%{
Expand All @@ -65,25 +65,24 @@ defmodule Hexpds.DidPlc do
})
end

@spec sign(t(), Hexpds.K256.PrivateKey.t()) ::
@spec sign(t(), Hipdster.K256.PrivateKey.t()) ::
{:ok, binary()} | {:error, String.t()}
def sign(%__MODULE__{} = operation, %Hexpds.K256.PrivateKey{} = privkey) do
def sign(%__MODULE__{} = operation, %Hipdster.K256.PrivateKey{} = privkey) do
with {:ok, cbor} <-
operation
|> to_json()
|> Hexpds.DagCBOR.encode(),
|> Hipdster.DagCBOR.encode(),
do:
{:ok,
privkey
|> Hexpds.K256.PrivateKey.sign(cbor)
|> Hexpds.K256.Signature.bytes()
|> Base.url_encode64()
|> String.replace("=", "")}
|> Hipdster.K256.PrivateKey.sign(cbor)
|> Hipdster.K256.Signature.bytes()
|> Base.url_encode64(padding: false)}
end

@spec add_sig(t(), Hexpds.K256.PrivateKey.t()) ::
@spec add_sig(t(), Hipdster.K256.PrivateKey.t()) ::
{:error, binary()} | map()
def add_sig(%__MODULE__{} = operation, %Hexpds.K256.PrivateKey{} = privkey) do
def add_sig(%__MODULE__{} = operation, %Hipdster.K256.PrivateKey{} = privkey) do
with {:ok, sig} <- sign(operation, privkey) do
operation
|> to_json
Expand Down
34 changes: 17 additions & 17 deletions lib/hexpds/k256.ex → lib/hipdster/k256.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Hexpds.K256 do
defmodule Hipdster.K256 do
@moduledoc """
Secp256k1-related functions, using the `k256` Rust crate.
Includes `Hexpds.K256.PrivateKey` and `Hexpds.K256.PublicKey`, which are type-safe wrappers around
Includes `Hipdster.K256.PrivateKey` and `Hipdster.K256.PublicKey`, which are type-safe wrappers around
raw bytes of keys and include wrappers around the `k256` crate's `k256::PublicKey` and `k256::SecretKey` types
and some of their helper functions required for ATProto.
"""
Expand All @@ -21,14 +21,14 @@ defmodule Hexpds.K256 do
# TODO: make this unnecessary
def bytes({:error, e}), do: raise(e)

@spec verify(t(), Hexpds.K256.PublicKey.t(), binary()) ::
@spec verify(t(), Hipdster.K256.PublicKey.t(), binary()) ::
{:ok, String.t()} | {:error, String.t()}
def verify(
%__MODULE__{sig: sig},
%{pubkey: pubkey, __struct__: Hexpds.K256.PublicKey},
%{pubkey: pubkey, __struct__: Hipdster.K256.PublicKey},
message
) do
case Hexpds.K256.Internal.verify_signature(pubkey, message, sig) do
case Hipdster.K256.Internal.verify_signature(pubkey, message, sig) do
true -> {:ok, "Signature #{inspect(sig)} verified"}
false -> {:error, "Signature #{inspect(sig)} could not be verified"}
tuple -> tuple
Expand All @@ -41,7 +41,7 @@ defmodule Hexpds.K256 do

@typedoc """
A Secp256k1 private key. Contains the raw bytes of the key, and wraps the `k256` crate's `k256::SecretKey` type.
Should always be 32 bytes (256 bits) long. All operations on `Hexpds.K256.PrivateKey` are type-safe.
Should always be 32 bytes (256 bits) long. All operations on `Hipdster.K256.PrivateKey` are type-safe.
"""
@type t :: %__MODULE__{privkey: <<_::256>>}

Expand Down Expand Up @@ -71,22 +71,22 @@ defmodule Hexpds.K256 do
def to_hex(%__MODULE__{privkey: privkey}) when is_valid_key(privkey),
do: Base.encode16(privkey, case: :lower)

@spec to_pubkey(t()) :: Hexpds.K256.PublicKey.t()
@spec to_pubkey(t()) :: Hipdster.K256.PublicKey.t()
def to_pubkey(%__MODULE__{} = privkey) when is_valid_key(privkey.privkey),
do: Hexpds.K256.PublicKey.create(privkey)
do: Hipdster.K256.PublicKey.create(privkey)

@spec sign(t(), binary()) :: {:error, String.t()} | Hexpds.K256.Signature.t()
@spec sign(t(), binary()) :: {:error, String.t()} | Hipdster.K256.Signature.t()
@doc """
Signs a binary message with a Secp256k1 private key. Returns a binary signature.
"""
def sign(%__MODULE__{privkey: privkey}, message)
when is_binary(message) and is_valid_key(privkey) do
with {:ok, sig} <- Hexpds.K256.Internal.sign_message(privkey, message),
with {:ok, sig} <- Hipdster.K256.Internal.sign_message(privkey, message),
{:ok, sig_bytes} <- Base.decode16(sig, case: :lower),
do: %Hexpds.K256.Signature{sig: sig_bytes}
do: %Hipdster.K256.Signature{sig: sig_bytes}
end

@spec sign!(t(), binary()) :: Hexpds.K256.Signature.t()
@spec sign!(t(), binary()) :: Hipdster.K256.Signature.t()
@doc """
Signs a binary message with a Secp256k1 private key. Returns a binary signature. Raises on error if signing fails.
"""
Expand All @@ -109,7 +109,7 @@ defmodule Hexpds.K256 do

@spec create(PrivateKey.t()) :: t()
def create(%PrivateKey{privkey: privkey}) do
case Hexpds.K256.Internal.create_public_key(privkey) do
case Hipdster.K256.Internal.create_public_key(privkey) do
{:ok, pubkey} -> from_binary(pubkey)
{:error, e} -> raise e
end
Expand All @@ -127,7 +127,7 @@ defmodule Hexpds.K256 do
Wrapper around the `k256` crate's `k256::PublicKey::compress` function.
"""
def compress(%__MODULE__{pubkey: pubkey}) do
case Hexpds.K256.Internal.compress_public_key(pubkey) do
case Hipdster.K256.Internal.compress_public_key(pubkey) do
{:ok, compressed} -> compressed
{:error, e} -> raise e
end
Expand All @@ -150,17 +150,17 @@ defmodule Hexpds.K256 do
(pubkey
|> compress()
|> Base.decode16!(case: :lower)
|> Hexpds.Multicodec.encode!(:"secp256k1-pub")
|> Hipdster.Multicodec.encode!(:"secp256k1-pub")
|> Multibase.encode!(:base58_btc))
end
end

defmodule Internal do
@moduledoc """
NIF for Rust crate k256. Raw APIs, do not use directly. Instead, use the
`Hexpds.K256.PublicKey` and `Hexpds.K256.PrivateKey` modules.
`Hipdster.K256.PublicKey` and `Hipdster.K256.PrivateKey` modules.
"""
use Rustler, otp_app: :hexpds, crate: "hexpds_k256_internal"
use Rustler, otp_app: :hipdster, crate: "hipdster_k256_internal"
@spec create_public_key(binary()) :: {:ok, binary()} | {:error, String.t()}
def create_public_key(_private_key), do: :erlang.nif_error(:nif_not_loaded)
@spec compress_public_key(binary()) :: {:ok, binary()} | {:error, String.t()}
Expand Down
1 change: 1 addition & 0 deletions lib/hipdster/mst.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

13 changes: 7 additions & 6 deletions lib/hexpds/multicodec.ex → lib/hipdster/multicodec.ex
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
defmodule Hexpds.Multicodec do
defmodule Hipdster.Multicodec do
use GenServer

def start_link(multicodec_csv \\ Application.get_env(:hexpds, :multicodec_csv_path)) do
def start_link(multicodec_csv \\ Application.get_env(:hipdster, :multicodec_csv_path)) do
GenServer.start_link(__MODULE__, multicodec_csv, name: __MODULE__)
end

@impl GenServer
def init(csv_path) do
{:ok, csv} = File.read(csv_path)
{:ok, read_csv(csv)}
{:ok,
csv_path
|> File.stream!()
|> read_csv()}
end

@impl GenServer
def handle_call(:multicodec_map, _from, state) do
{:reply, state, state}
end

def read_csv(csv) do
def read_csv(%File.Stream{} = csv) do
csv
|> String.split("\n", trim: true)
|> Stream.map(&String.replace(&1, " ", ""))
|> Stream.map(&String.split(&1, ",", trim: true))
|> Enum.reduce(%{}, fn [name, _tag, "0x" <> code, _status], acc ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule RecordConverter do
alias Hexpds.CID, as: CID
alias Hipdster.CID, as: CID

# Converts a record to a JSON-compatible format.
def record_to_json(record) do
Expand Down
10 changes: 5 additions & 5 deletions lib/hexpds/tid.ex → lib/hipdster/tid.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Hexpds.Tid do
defmodule Hipdster.Tid do
import Bitwise

defstruct [:timestamp, :clock_id]
Expand Down Expand Up @@ -66,9 +66,9 @@ defmodule Hexpds.Tid do
end
end

defimpl String.Chars, for: Hexpds.Tid do
@spec to_string(Hexpds.Tid.t()) :: String.t()
defdelegate to_string(tid), to: Hexpds.Tid
defimpl String.Chars, for: Hipdster.Tid do
@spec to_string(Hipdster.Tid.t()) :: String.t()
defdelegate to_string(tid), to: Hipdster.Tid
end

@doc """
Expand Down Expand Up @@ -107,7 +107,7 @@ defmodule Hexpds.Tid do
- Then, the `clock_id` `c` is combined into this value using the bitwise OR operation.
- Resulting integer combines both the timestamp and clock_id in a single integer.
"""
@spec to_integer(Hexpds.Tid.t()) :: integer()
@spec to_integer(Hipdster.Tid.t()) :: integer()
def to_integer(%__MODULE__{timestamp: t, clock_id: c}) do
t <<< 10 ||| c
end
Expand Down
Loading
Loading