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

Bls validation #1566

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
13 changes: 6 additions & 7 deletions lib/archethic/crypto.ex
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ defmodule Archethic.Crypto do
private_key = :crypto.hash(:sha512, seed)

keypair = {
BlsEx.get_public_key(private_key),
BlsEx.get_public_key!(private_key),
private_key
}

Expand Down Expand Up @@ -442,7 +442,7 @@ defmodule Archethic.Crypto do
end

defp do_sign(:ed25519, data, key), do: Ed25519.sign(key, data)
defp do_sign(:bls, data, key), do: BlsEx.sign(key, data)
defp do_sign(:bls, data, key), do: BlsEx.sign!(key, data)
defp do_sign(curve, data, key), do: ECDSA.sign(curve, key, data)

@doc """
Expand Down Expand Up @@ -562,8 +562,7 @@ defmodule Archethic.Crypto do
signature :: binary(),
data :: iodata() | bitstring() | [bitstring],
public_key :: key()
) ::
boolean()
) :: boolean()
def verify?(
sig,
data,
Expand All @@ -576,7 +575,7 @@ defmodule Archethic.Crypto do
end

defp do_verify?(:ed25519, key, data, sig), do: Ed25519.verify?(key, data, sig)
defp do_verify?(:bls, key, data, sig), do: BlsEx.verify_signature(key, data, sig)
defp do_verify?(:bls, key, data, sig), do: BlsEx.verify_signature?(key, data, sig)
defp do_verify?(curve, key, data, sig), do: ECDSA.verify?(curve, key, data, sig)

@doc """
Expand Down Expand Up @@ -1436,7 +1435,7 @@ defmodule Archethic.Crypto do
"""
@spec aggregate_signatures(signatures :: list(binary()), public_keys :: list(key())) :: binary()
def aggregate_signatures(signatures, public_keys) do
BlsEx.aggregate_signatures(
BlsEx.aggregate_signatures!(
signatures,
Enum.map(public_keys, fn <<_::8, _::8, public_key::binary>> -> public_key end)
)
Expand All @@ -1449,7 +1448,7 @@ defmodule Archethic.Crypto do
def aggregate_mining_public_keys(public_keys) do
public_keys
|> Enum.map(fn <<_::8, _::8, public_key::binary>> -> public_key end)
|> BlsEx.aggregate_public_keys()
|> BlsEx.aggregate_public_keys!()
|> ID.prepend_key(:bls)
end
end
2 changes: 0 additions & 2 deletions lib/archethic/db.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ defmodule Archethic.DB do
Crypto.prepended_hash() | nil
@callback get_last_chain_address(binary()) :: {binary(), DateTime.t()}
@callback get_last_chain_address(binary(), DateTime.t()) :: {binary(), DateTime.t()}
@callback get_last_chain_public_key(binary()) :: Crypto.key()
@callback get_last_chain_public_key(binary(), DateTime.t()) :: Crypto.key()
@callback get_genesis_address(address :: Crypto.prepended_hash()) ::
genesis_address :: Crypto.prepended_hash()
@callback find_genesis_address(address :: Crypto.prepended_hash()) ::
Expand Down
9 changes: 0 additions & 9 deletions lib/archethic/db/embedded_impl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -251,15 +251,6 @@ defmodule Archethic.DB.EmbeddedImpl do
ChainIndex.get_last_chain_address(address, date, filepath())
end

@doc """
Return the last public key from the given public key until the given date along with its timestamp
"""
@spec get_last_chain_public_key(public_key :: binary(), until :: DateTime.t()) :: Crypto.key()
def get_last_chain_public_key(public_key, date = %DateTime{} \\ DateTime.utc_now())
when is_binary(public_key) do
ChainIndex.get_last_chain_public_key(public_key, date, filepath())
end

@doc """
Reference a last address from a genesis address
"""
Expand Down
44 changes: 0 additions & 44 deletions lib/archethic/db/embedded_impl/chain_index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -677,50 +677,6 @@ defmodule Archethic.DB.EmbeddedImpl.ChainIndex do
end
end

@doc """
Return the last public key of a chain until a date

If no key is found, the given public key is returned
"""
@spec get_last_chain_public_key(Crypto.key(), DateTime.t(), String.t()) :: Crypto.key()
def get_last_chain_public_key(public_key, until = %DateTime{}, db_path) do
# We derive the previous address from the public key to get the genesis address
# and its relative file
address = Crypto.derive_address(public_key)
genesis_address = get_genesis_address(address, db_path)
filepath = chain_keys_path(db_path, genesis_address)

until = DateTime.to_unix(until, :millisecond)

case File.open(filepath, [:binary, :read]) do
{:ok, fd} ->
do_get_last_public_key(fd, until, public_key)

{:error, _} ->
public_key
end
end

defp do_get_last_public_key(fd, until, last_public_key) do
# We need to extract key metadata information to know how many bytes to decode
# as keys can have different sizes based on the curve used
with {:ok, <<timestamp::64, curve_id::8, origin_id::8>>} <- :file.read(fd, 10),
key_size <- Crypto.key_size(curve_id),
{:ok, key} <- :file.read(fd, key_size) do
if timestamp < until do
public_key = <<curve_id::8, origin_id::8, key::binary>>
do_get_last_public_key(fd, until, public_key)
else
:file.close(fd)
last_public_key
end
else
:eof ->
:file.close(fd)
last_public_key
end
end

@doc """
Stream all the file stats entries to indentify the addresses
"""
Expand Down
59 changes: 25 additions & 34 deletions lib/archethic/mining.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ defmodule Archethic.Mining do
alias Archethic.Election

alias __MODULE__.DistributedWorkflow
alias __MODULE__.Error
alias __MODULE__.Fee
alias __MODULE__.StandaloneWorkflow
alias __MODULE__.WorkerSupervisor
Expand All @@ -23,6 +22,7 @@ defmodule Archethic.Mining do

alias Archethic.TransactionChain.Transaction
alias Archethic.TransactionChain.Transaction.CrossValidationStamp
alias Archethic.TransactionChain.Transaction.ProofOfValidation
alias Archethic.TransactionChain.Transaction.ValidationStamp

alias Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperations.VersionedUnspentOutput
Expand Down Expand Up @@ -224,11 +224,29 @@ defmodule Archethic.Mining do
@doc """
Add a cross validation stamp to the transaction mining process
"""
@spec add_cross_validation_stamp(binary(), stamp :: CrossValidationStamp.t()) :: :ok
def add_cross_validation_stamp(tx_address, stamp = %CrossValidationStamp{}) do
@spec add_cross_validation_stamp(
tx_address :: Crypto.prepended_hash(),
stamp :: CrossValidationStamp.t(),
from :: Crypto.key()
) :: :ok
def add_cross_validation_stamp(tx_address, stamp = %CrossValidationStamp{}, from) do
pid = get_mining_process!(tx_address)
if pid, do: send(pid, {:add_cross_validation_stamp, stamp, from})
:ok
end

@doc """
Add a proof of validation to the transaction mining process
"""
@spec add_proof_of_validation(
tx_address :: Crypto.prepended_hash(),
proof_of_validation :: ProofOfValidation.t(),
from :: Crypto.key()
Neylix marked this conversation as resolved.
Show resolved Hide resolved
) :: :ok
def add_proof_of_validation(tx_address, proof, from) do
tx_address
|> get_mining_process!()
|> DistributedWorkflow.add_cross_validation_stamp(stamp)
|> DistributedWorkflow.add_proof_of_validation(proof, from)
end

@doc """
Expand All @@ -238,41 +256,14 @@ defmodule Archethic.Mining do
address :: binary(),
signature :: binary(),
node_public_key :: Crypto.key()
) ::
:ok
) :: :ok
def confirm_replication(tx_address, signature, node_public_key) do
pid = get_mining_process!(tx_address, 1000)
pid = get_mining_process!(tx_address)
if pid, do: send(pid, {:ack_replication, signature, node_public_key})
:ok
end

@doc """
Notify replication to the mining process
"""
@spec notify_replication_error(
address :: binary(),
error :: Error.t(),
Crypto.key()
) :: :ok
def notify_replication_error(tx_address, error, node_public_key) do
pid = get_mining_process!(tx_address, 1_000)

if pid, do: DistributedWorkflow.replication_error(pid, error, node_public_key)

:ok
end

@doc """
Notify about the validation from a replication node
"""
@spec notify_replication_validation(binary(), Crypto.key()) :: :ok
def notify_replication_validation(tx_address, node_public_key) do
pid = get_mining_process!(tx_address, 1_000)
if pid, do: DistributedWorkflow.add_replication_validation(pid, node_public_key)
:ok
end

defp get_mining_process!(tx_address, timeout \\ 3_000) do
defp get_mining_process!(tx_address, timeout \\ 1000) do
retry_while with: constant_backoff(100) |> expiry(timeout) do
case Registry.lookup(WorkflowRegistry, tx_address) do
[{pid, _}] ->
Expand Down
Loading
Loading