Skip to content

Commit

Permalink
Merge pull request #298 from kommitters/v0.14
Browse files Browse the repository at this point in the history
Release v0.14.0
  • Loading branch information
Odraxs authored May 8, 2023
2 parents 17a83bc + b29acf9 commit 56cda9b
Show file tree
Hide file tree
Showing 8 changed files with 364 additions and 19 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 0.14.0 (08.05.2023)

* Add `sign_xdr` function to `ContractAuth` module to allow signing base 64 contract auth structures.
* Update `InvokeHostFunction` module to allow adding base 64 authorizations.

## 0.13.1 (02.05.2023)
* Update `SCAddress` module to infer address types: account or contract.
* Update all dependencies
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ The **Stellar SDK** is composed of two complementary components: **`TxBuild`** +
```elixir
def deps do
[
{:stellar_sdk, "~> 0.13.1"}
{:stellar_sdk, "~> 0.14.0"}
]
end
```
Expand Down
62 changes: 61 additions & 1 deletion lib/tx_build/contract_auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ defmodule Stellar.TxBuild.ContractAuth do
}

alias Stellar.{KeyPair, Network}
alias StellarBase.XDR.{ContractAuth, SCVec}
alias StellarBase.XDR.{ContractAuth, EnvelopeType, SCVec}
alias StellarBase.XDR.HashIDPreimage, as: HashIDPreimageXDR
alias StellarBase.XDR.Hash, as: HashXDR
alias StellarBase.XDR.HashIDPreimageContractAuth, as: HashIDPreimageContractAuthXDR

alias Stellar.TxBuild.{
AddressWithNonce,
Expand Down Expand Up @@ -132,6 +134,64 @@ defmodule Stellar.TxBuild.ContractAuth do

def sign(_args, _val), do: {:error, :invalid_secret_key}

@spec sign_xdr(base_64 :: binary(), secret_key :: binary()) :: binary()
def sign_xdr(base_64, secret_key) do
{public_key, _secret_key} = KeyPair.from_secret_seed(secret_key)
raw_public_key = KeyPair.raw_public_key(public_key)
network_id = network_id_xdr()

{%ContractAuth{
address_with_nonce: %{
address_with_nonce: %{
nonce: nonce
}
},
authorized_invocation: authorized_invocation
} = contract_auth,
""} =
base_64
|> Base.decode64!()
|> ContractAuth.decode_xdr!()

envelope_type = EnvelopeType.new(:ENVELOPE_TYPE_CONTRACT_AUTH)

signature =
network_id
|> HashXDR.new()
|> HashIDPreimageContractAuthXDR.new(nonce, authorized_invocation)
|> HashIDPreimageXDR.new(envelope_type)
|> HashIDPreimageXDR.encode_xdr!()
|> hash()
|> KeyPair.sign(secret_key)

public_key_map_entry =
SCMapEntry.new(
SCVal.new(symbol: "public_key"),
SCVal.new(bytes: raw_public_key)
)

signature_map_entry =
SCMapEntry.new(
SCVal.new(symbol: "signature"),
SCVal.new(bytes: signature)
)

signature_args = [SCVal.new(map: [public_key_map_entry, signature_map_entry])]

signature_xdr_val =
[vec: signature_args]
|> SCVal.new()
|> SCVal.to_xdr()
|> (&SCVec.new([&1])).()

%{
contract_auth
| signature_args: signature_xdr_val
}
|> ContractAuth.encode_xdr!()
|> Base.encode64()
end

@spec network_id_xdr :: binary()
defp network_id_xdr, do: hash(Network.passphrase())

Expand Down
54 changes: 44 additions & 10 deletions lib/tx_build/invoke_host_function.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule Stellar.TxBuild.InvokeHostFunction do
alias Stellar.TxBuild.{ContractAuth, HostFunction, OptionalAccount}

alias StellarBase.XDR.Operations.InvokeHostFunction
alias StellarBase.XDR.ContractAuth, as: ContractAuthXDR

alias StellarBase.XDR.{
OperationBody,
Expand All @@ -27,7 +28,7 @@ defmodule Stellar.TxBuild.InvokeHostFunction do
@type t :: %__MODULE__{
function: HostFunction.t(),
footprint: String.t(),
auth: list(ContractAuth.t()),
auth: list(ContractAuth.t()) | String.t(),
source_account: OptionalAccount.t()
}

Expand All @@ -43,7 +44,7 @@ defmodule Stellar.TxBuild.InvokeHostFunction do
source_account = Keyword.get(args, :source_account)

with {:ok, function} <- validate_function(function),
{:ok, footprint} <- validate_footprint({:footprint, footprint}),
{:ok, footprint} <- validate_xdr_string({:xdr, footprint}),
{:ok, source_account} <- validate_optional_account({:source_account, source_account}),
{:ok, auth} <- validate_auth(auth) do
%__MODULE__{
Expand Down Expand Up @@ -110,6 +111,32 @@ defmodule Stellar.TxBuild.InvokeHostFunction do
|> OperationBody.new(op_type)
end

def to_xdr(%__MODULE__{
function: function,
footprint: footprint,
auth: auth
})
when is_binary(auth) do
op_type = OperationType.new(:INVOKE_HOST_FUNCTION)
host_function = HostFunction.to_xdr(function)

{ledger_footprint, _} =
footprint
|> Base.decode64!()
|> LedgerFootprint.decode_xdr!()

{contract_auth, ""} =
auth
|> Base.decode64!()
|> ContractAuthXDR.decode_xdr!()

contract_auth_list = ContractAuthList.new([contract_auth])

host_function
|> InvokeHostFunction.new(ledger_footprint, contract_auth_list)
|> OperationBody.new(op_type)
end

def to_xdr(%__MODULE__{
function: function,
footprint: footprint,
Expand All @@ -132,26 +159,33 @@ defmodule Stellar.TxBuild.InvokeHostFunction do

@spec set_footprint(module :: t(), footprint :: String.t()) :: t()
def set_footprint(%__MODULE__{} = module, footprint) do
with {:ok, footprint} <- validate_footprint({:footprint, footprint}) do
with {:ok, footprint} <- validate_xdr_string({:xdr, footprint}) do
%{module | footprint: footprint}
end
end

@spec set_contract_auth(module :: t(), auth :: String.t()) :: t()
def set_contract_auth(%__MODULE__{} = module, auth) when is_binary(auth) do
with {:ok, auth} <- validate_xdr_string({:xdr, auth}) do
%{module | auth: auth}
end
end

@spec validate_function(function :: HostFunction.t()) :: validation()
defp validate_function(%HostFunction{} = function), do: {:ok, function}
defp validate_function(_), do: {:error, :invalid_function}

@spec validate_footprint(tuple :: tuple()) :: validation()
defp validate_footprint({:footprint, nil}), do: {:ok, nil}
@spec validate_xdr_string(tuple :: tuple()) :: validation()
defp validate_xdr_string({:xdr, nil}), do: {:ok, nil}

defp validate_footprint({:footprint, footprint}) when is_binary(footprint) do
case Base.decode64(footprint) do
{:ok, _} -> {:ok, footprint}
:error -> {:error, :invalid_footprint}
defp validate_xdr_string({:xdr, xdr}) when is_binary(xdr) do
case Base.decode64(xdr) do
{:ok, _} -> {:ok, xdr}
:error -> {:error, :invalid_xdr}
end
end

defp validate_footprint({:footprint, _}), do: {:error, :invalid_footprint}
defp validate_xdr_string({:xdr, _}), do: {:error, :invalid_xdr}

@spec validate_auth(function :: list(ContractAuth.t())) :: validation()
defp validate_auth([%ContractAuth{} | _] = auth), do: {:ok, auth}
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Stellar.MixProject do
use Mix.Project

@github_url "https://github.com/kommitters/stellar_sdk"
@version "0.13.1"
@version "0.14.0"

def project do
[
Expand Down
Loading

0 comments on commit 56cda9b

Please sign in to comment.