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

Specify the hash algorithm in the sc library functions #610 #834

Merged
merged 1 commit into from
Jan 24, 2023
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
32 changes: 29 additions & 3 deletions lib/archethic/contracts/interpreter/library.ex
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,38 @@ defmodule Archethic.Contracts.Interpreter.Library do

## Examples

iex> Library.hash("hello","sha256")
"2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824"

iex> Library.hash("hello")
"2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824"
"""
@spec hash(binary()) :: binary()
def hash(content) when is_binary(content) do
:crypto.hash(:sha256, decode_binary(content)) |> Base.encode16()
@spec hash(
content :: binary(),
algo :: binary()
) ::
binary()
def hash(content, algo \\ "sha256") when is_binary(content) do
algo =
case algo do
"sha256" ->
:sha256

"sha512" ->
:sha512

"sha3_256" ->
:sha3_256

"sha3_512" ->
:sha3_512

"blake2b" ->
:blake2b
end

:crypto.hash(algo, decode_binary(content))
|> Base.encode16()
end

@doc """
Expand Down
7 changes: 7 additions & 0 deletions lib/archethic/contracts/interpreter/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ defmodule Archethic.Contracts.Interpreter.Utils do
)
|> Enum.into(%{})

@supported_hash Archethic.Crypto.list_supported_hash_functions(:string)

@transaction_fields [
"address",
"type",
Expand Down Expand Up @@ -220,6 +222,11 @@ defmodule Archethic.Contracts.Interpreter.Utils do
when scope != :root,
do: {node, acc}

# Whitelist the hash/2 function
def prewalk(node = {{:atom, "hash"}, _, [_data, algo]}, acc = {:ok, %{scope: scope}})
when scope != :root and algo in @supported_hash,
do: {node, acc}

# Whitelist the regex_match?/2 function
def prewalk(
node = {{:atom, "regex_match?"}, _, [_input, _search]},
Expand Down
5 changes: 5 additions & 0 deletions lib/archethic/crypto.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1315,4 +1315,9 @@ defmodule Archethic.Crypto do
def authorized_key_origin?(<<_::8, _::8, _::binary>>, []) do
true
end

@supported_hashes Application.compile_env(:archethic, [__MODULE__, :supported_hashes])
def list_supported_hash_functions(), do: @supported_hashes
@string_hashes Enum.map(@supported_hashes, &Atom.to_string/1)
def list_supported_hash_functions(:string), do: @string_hashes
end
40 changes: 40 additions & 0 deletions test/archethic/contracts/interpreter/action_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -343,4 +343,44 @@ defmodule Archethic.Contracts.ActionInterpreterTest do
|> elem(2)
|> ActionInterpreter.execute()
end

describe "Hash in action" do
test "Hash/2 blake2b" do
assert %Transaction{data: %TransactionData{content: "yes"}} =
~s"""
actions triggered_by: transaction do
address = hash("hello darkness ","blake2b")
if address == "CCFF7E67D673C76E3AAA242BF6B726DD75EF1C5AA201A527CFC76754B23AE0EAF83960DFC9377C4EDA7CF25EF3A9D0E66B54A3993F8AC2ECB5CA9CBDB79454F7" do
set_content "yes"
else
set_content "no"
end
end
"""
|> Interpreter.sanitize_code()
|> elem(1)
|> ActionInterpreter.parse()
|> elem(2)
|> ActionInterpreter.execute()
end

test "Hash/1" do
assert %Transaction{data: %TransactionData{content: "yes"}} =
~s"""
actions triggered_by: transaction do
address = hash("hello darkness ")
if address == "E96FC07DD7B9EE9CDA01DF26DC9AFA78388EB33B12FDB8619C27BEAA3130CF18" do
set_content "yes"
else
set_content "no"
end
end
"""
|> Interpreter.sanitize_code()
|> elem(1)
|> ActionInterpreter.parse()
|> elem(2)
|> ActionInterpreter.execute()
end
end
end
2 changes: 1 addition & 1 deletion test/archethic/contracts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ defmodule Archethic.ContractsTest do
]

actions triggered_by: transaction do
add_uco_transfer to: "\3265CCD78CD74984FAB3CC6984D30C8C82044EBBAB1A4FFFB683BDB2D8C5BCF9", amount: 1000000000
add_uco_transfer to: \"3265CCD78CD74984FAB3CC6984D30C8C82044EBBAB1A4FFFB683BDB2D8C5BCF9\", amount: 1000000000
set_content "hello"
set_type transfer
end
Expand Down