Skip to content
Snippets Groups Projects
Commit aaaf6862 authored by ABDELGHANI Nassim's avatar ABDELGHANI Nassim
Browse files

Merge branch '192-validation-locale' into 'dev'

Resolve "Validation locale"

Closes #192

See merge request dunixir/dunixir!46
parents ac81f88a f26909ec
Branches
Tags
1 merge request!46Resolve "Validation locale"
Pipeline #4321 passed
Showing
with 140 additions and 11 deletions
defmodule Block.Validation.Local do
def valid(block) do
[
Block.Validation.Local.Version,
Block.Validation.Local.InnerHash,
Block.Validation.Local.Nonce,
Block.Validation.Local.ProofOfWork,
Block.Validation.Local.PreviousHash,
Block.Validation.Local.PreIssuer,
Block.Validation.Local.Parameters,
Block.Validation.Local.UniversalDividend,
Block.Validation.Local.UnitBase,
Block.Validation.Local.BlockSignature,
Block.Validation.Local.BlockTime,
Block.Validation.Local.IdentitySignature,
Block.Validation.Local.MembershipSig,
Block.Validation.Local.TransactionNumberOfLines,
Block.Validation.Local.TransactionInput,
Block.Validation.Local.TxInfNbIssuers,
Block.Validation.Local.TransactionVersion,
Block.Validation.Local.TransactionCount,
Block.Validation.Local.TxSigOrdered
]
|> Enum.all?(fn module -> module.valid(block) end)
|> then(fn is_valid ->
if is_valid do
case Index.Generation.process(block) do
{:ok, [local_iindex, local_mindex, local_cindex, local_sindex]} ->
if IndexRules.check(local_iindex, local_mindex, local_cindex, local_sindex) do
{:ok, [local_iindex, local_mindex, local_cindex, local_sindex]}
else
{:error, "Index rules not satisfied"}
end
{:error, error} ->
{:error, error}
end
else
{:error, "Block is not valid"}
end
end)
end
end
defmodule Block.Validation.Local.BlockSignature do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#signature
"""
require Logger
def invalid_g1_block() do
......
defmodule Block.Validation.Local.BlockTime do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#dates-1
"""
require Logger
# @default_avg_gen_time 16 * 60
......
defmodule Block.Validation.Local.PreIssuer do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#previousissuer
"""
def valid(block) do
not (block["number"] == 0 and
block["previousIssuer"] != nil) and
......
defmodule Block.Validation.Local.UnitBase do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#unitbase
"""
def valid(block) do
not (block["unitbase"] != 0 and block["number"] == 0)
end
......
defmodule Block.Validation.Local.IdentitySignature do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#identities
"""
def valid(block) do
Doc.Identity.local_validation(block["identities"], block["currency"])
end
......
defmodule Block.Validation.Local.InnerHash do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#innerhash
"""
def valid(block) do
computed_hash =
:crypto.hash(:sha256, _get_raw_inner_part(block))
......@@ -38,7 +41,7 @@ defmodule Block.Validation.Local.InnerHash do
#{if block["dividend"] do
"UniversalDividend: #{block["dividend"]}\n"
end}\
UnitBase: #{block["unitBase"]}
UnitBase: #{block["unitbase"]}
Issuer: #{block["issuer"]}
IssuersFrame: #{block["issuersFrame"]}
IssuersFrameVar: #{block["issuersFrameVar"]}
......@@ -49,7 +52,7 @@ defmodule Block.Validation.Local.InnerHash do
#{if block["previousIssuer"] do
"PreviousIssuer: #{block["previousIssuer"]}\n"
end}\
#{if block["parameters"] do
#{if block["parameters"] && block["parameters"] != "" do
"Parameters: #{block["parameters"]}\n"
end}\
MembersCount: #{block["membersCount"]}
......
defmodule Block.Validation.Local.MembershipSig do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#memberships-joiners-actives-leavers
"""
def valid(block) do
Doc.Membership.local_validation(
block["joiners"],
......
defmodule Block.Validation.Local.Nonce do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#nonce
"""
def valid(block) do
block["nonce"] >= 0
is_integer(block["nonce"]) and block["nonce"] >= 0
end
end
defmodule Block.Validation.Local.Parameters do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#parameters
"""
def valid(block) do
(block["number"] == 0 and block["parameters"] != "") or
(block["number"] > 0 and block["parameters"] == "")
......
defmodule Block.Validation.Local.PreviousHash do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#previoushash
"""
def valid(block) do
cond do
block["number"] > 0 ->
......
defmodule Block.Validation.Local.ProofOfWork do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#proof-of-work
"""
def valid(block) do
required_zeros = div(block["powMin"], 16)
String.match?(block["hash"], ~r/^0{#{required_zeros}}/)
......
defmodule Block.Validation.Local.TransactionCount do
@moduledoc """
Signatures count must be the same as issuers count
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#transactions
"""
def valid(block) do
Enum.all?(block["transactions"], fn element ->
length(element["signatures"]) == length(element["issuers"])
......
defmodule Block.Validation.Local.TxInfNbIssuers do
@moduledoc """
A transaction cannot have SIG(INDEX) unlocks with INDEX >= issuers count.
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#transactions
"""
def valid(block) do
case block["transactions"] do
# Since there is no transaction field, there is no transaction to check
......@@ -31,20 +36,21 @@ defmodule Block.Validation.Local.TxInfNbIssuers do
end
@doc """
Checks every unlock is below the number of issuers
Checks every unlock SIG index value is below the number of issuers
"""
def _checkUnlocks(_issuerCount, []) do
true
end
def _checkUnlocks(issuerCount, [unlock | tail]) do
_getSIGValue(unlock) <= issuerCount - 1 and _checkUnlocks(issuerCount, tail)
_getSIGValues(unlock) |> Enum.all?(fn [sig_value] -> String.to_integer(sig_value) <= issuerCount - 1 end) and
_checkUnlocks(issuerCount, tail)
end
@doc """
Returns the number between the brackets
Returns the index values of SIG unlocks
"""
def _getSIGValue(str) do
String.to_integer(Enum.at(String.split(str, ["(", ")"]), 1))
def _getSIGValues(unlock) do
Regex.compile!("SIG\\((\\d+)\\)") |> Regex.scan(unlock, capture: :all_but_first)
end
end
defmodule Block.Validation.Local.TransactionInput do
@moduledoc """
A transaction must have at least 1 source
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#transactions
"""
def valid(block) do
case block["transactions"] do
[] ->
......
defmodule Block.Validation.Local.TransactionNumberOfLines do
@moduledoc """
A transaction in [compact format](https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#compact-format) cannot measure more than 100 lines
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#transactions
"""
def valid(block) do
length(block["transactions"]) < 100
block["transactions"]
|> Enum.all?(fn transaction -> compact_format_length(transaction) < 100 end)
end
defp compact_format_length(transaction) do
# header + blockstamp
# issuers + signatures
# inputs + unlocks
2 +
length(transaction["issuers"]) * 2 +
length(transaction["inputs"]) * 2 +
if(transaction["comment"] && String.length(transaction["comment"]) > 0,
do: 1,
else: 0
) + length(transaction["outputs"])
end
end
defmodule Block.Validation.Local.TransactionVersion do
@moduledoc """
Transaction's version must be equal to 10.
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#transactions
"""
def valid(block) do
Enum.all?(block["transactions"], fn element -> element["version"] == 10 end)
end
......
defmodule Block.Validation.Local.TxSigOrdered do
@moduledoc """
A transaction must have signatures matching its content for each issuer
Signatures are ordered by issuer
Signatures are made over the transaction's content, signatures excepted
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#transactions
"""
def valid(block) do
_valid_tx(block["transactions"])
end
......
defmodule Block.Validation.Local.UniversalDividend do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#universal-dividend
"""
def valid(block) do
block["number"] === 0 and block["dividend"] === nil
if block["number"] === 0, do: block["dividend"] === nil, else: true
end
end
defmodule Block.Validation.Local.Version do
@moduledoc """
https://git.duniter.org/documents/rfcs/-/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md#version
"""
def valid(block) do
block["version"] >= 10
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment