Current section
Files
Jump to
Current section
Files
lib/forge/tx.ex
defmodule Forge.Tx do
@moduledoc """
Transaction manipulation for Forge
"""
alias Forge.{Crypto, Rpc, TransactionMessage}
@doc """
Sign the transaction with private key
"""
@spec sign(TransactionMessage.t(), binary()) :: binary()
def sign(tx, priv_key) do
tx = %TransactionMessage{tx | signature: <<>>}
hash = Crypto.sha3(TransactionMessage.encode(tx))
signature = Crypto.ecdsa_sign!(hash, priv_key)
tx = %TransactionMessage{tx | signature: Base.encode64(signature)}
TransactionMessage.encode(tx)
end
@doc """
Sign and deliver a transaction into the blockchain network
"""
@spec deliver(TransactionMessage.t(), String.t()) :: :ok | {:error, any}
def deliver(tx, priv_key) do
tx
|> sign(priv_key)
|> Rpc.send()
end
@doc """
Verify the signature of the transaction
"""
@spec verify(TransactionMessage.t()) :: :ok | :error
def verify(tx) do
signature = Base.decode64!(tx.signature)
tx = %TransactionMessage{tx | signature: <<>>}
hash = Crypto.sha3(TransactionMessage.encode(tx))
Crypto.ecdsa_verify(hash, signature, tx.public_key)
end
end
defmodule Forge.Tx.TransferTransaction do
@moduledoc """
Generate transfer tx
"""
alias Forge.{TransactionMessage, TransferMessage, Tx}
@doc """
Create a transfer transaction and sign it properly
"""
@spec create(String.t(), String.t(), non_neg_integer(), non_neg_integer(), binary(), binary()) ::
binary()
def create(from, to, nonce, total, public_key, private_key) do
tx = %TransactionMessage{
from: from,
nonce: nonce,
public_key: public_key,
signature: <<>>,
value:
{:transfer,
%TransferMessage{
to: to,
total: total
}}
}
Tx.sign(tx, private_key)
end
end
defmodule Forge.Tx.CustomTransaction do
@moduledoc """
Generate transfer tx
"""
alias Forge.{TransactionMessage, Tx}
alias Google.Protobuf.Any
@doc """
Create a transfer transaction and sign it properly
"""
@spec create(String.t(), non_neg_integer, String.t(), module(), map(), String.t(), String.t()) ::
binary()
def create(from, nonce, type_url, type_mod, attrs, public_key, private_key) do
value = type_mod.encode(type_mod.new(attrs))
tx = %TransactionMessage{
from: from,
nonce: nonce,
public_key: public_key,
signature: <<>>,
value:
{:any,
%Any{
type_url: type_url,
value: value
}}
}
Tx.sign(tx, private_key)
end
end