Skip to main content

txtx_core/std/functions/
hash.rs

1use ripemd::{Digest, Ripemd160 as LibRipemd160};
2use txtx_addon_kit::keccak_hash::keccak;
3use txtx_addon_kit::sha2::Sha256 as LibSha256;
4use txtx_addon_kit::types::AuthorizationContext;
5
6use txtx_addon_kit::{
7    define_function, indoc,
8    types::{
9        diagnostics::Diagnostic,
10        functions::{FunctionImplementation, FunctionSpecification},
11        types::{Type, Value},
12    },
13};
14
15use super::arg_checker;
16use crate::std::typing::StdValue;
17
18lazy_static! {
19    pub static ref FUNCTIONS: Vec<FunctionSpecification> = vec![
20        define_function! {
21            Ripemd160 => {
22                name: "ripemd160",
23                documentation: "`ripemd160` computes the Ripemd160 hash of a value.",
24                example: indoc!{r#"
25                output "hashed_data" {
26                    value = ripemd160(encode_hex("hello, world"))
27                }
28                // > hashed_data: 0XA3201F82FCA034E46D10CD7B27E174976E241DA2
29              "#},
30                inputs: [
31                    value: {
32                        documentation: "The hex-encoded value to hash.",
33                        typing: vec![Type::buffer(), Type::array(Type::buffer())]
34                    }
35                ],
36                output: {
37                    documentation: "The hashed result.",
38                    typing: Type::string()
39                },
40            }
41        },
42        define_function! {
43            Sha256 => {
44                name: "sha256",
45                documentation: "`sha256` computes the sha256 hash of a value.",
46                example: indoc!{r#"
47                output "hashed_data" {
48                    value = sha256(encode_hex("hello, world"))
49                }
50                // > hashed_data: 0x09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b
51              "#},
52                inputs: [
53                    value: {
54                        documentation: "The hex-encoded value to hash.",
55                        typing: vec![Type::buffer(), Type::array(Type::buffer())]
56                    }
57                ],
58                output: {
59                    documentation: "The hashed result.",
60                    typing: Type::string()
61                },
62            }
63        },
64        define_function! {
65            Keccak256 => {
66                name: "keccak256",
67                documentation: "`std::keccak256` computes the keccak256 hash of a value.",
68                example: indoc!{r#"
69                output "hashed_data" {
70                    value = keccak256("hello, world")
71                }
72                // > hashed_data: 0x09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b
73              "#},
74                inputs: [
75                    value: {
76                        documentation: "The string value to hash.",
77                        typing: vec![Type::string()]
78                    }
79                ],
80                output: {
81                    documentation: "The hashed result.",
82                    typing: Type::string()
83                },
84            }
85        }
86    ];
87}
88
89pub struct Ripemd160;
90impl FunctionImplementation for Ripemd160 {
91    fn check_instantiability(
92        _fn_spec: &FunctionSpecification,
93        _auth_ctx: &AuthorizationContext,
94        _args: &Vec<Type>,
95    ) -> Result<Type, Diagnostic> {
96        unimplemented!()
97    }
98
99    fn run(
100        fn_spec: &FunctionSpecification,
101        _auth_ctx: &AuthorizationContext,
102        args: &Vec<Value>,
103    ) -> Result<Value, Diagnostic> {
104        let Some(value) = args.get(0) else {
105            return Err(diagnosed_error!("{}: expected 1 argument, got 0", fn_spec.name));
106        };
107
108        let mut hasher = LibRipemd160::new();
109        hasher.update(value.to_be_bytes());
110        let result = hasher.finalize();
111        Ok(StdValue::hash(result[..].to_vec()))
112    }
113}
114
115pub struct Sha256;
116impl FunctionImplementation for Sha256 {
117    fn check_instantiability(
118        _fn_spec: &FunctionSpecification,
119        _auth_ctx: &AuthorizationContext,
120        _args: &Vec<Type>,
121    ) -> Result<Type, Diagnostic> {
122        unimplemented!()
123    }
124
125    fn run(
126        fn_spec: &FunctionSpecification,
127        _auth_ctx: &AuthorizationContext,
128        args: &Vec<Value>,
129    ) -> Result<Value, Diagnostic> {
130        let Some(value) = args.get(0) else {
131            return Err(diagnosed_error!("{}: expected 1 argument, got 0", fn_spec.name));
132        };
133
134        let mut hasher = LibSha256::new();
135        hasher.update(value.to_be_bytes());
136        let result = hasher.finalize();
137        Ok(StdValue::hash(result[..].to_vec()))
138    }
139}
140
141pub struct Keccak256;
142impl FunctionImplementation for Keccak256 {
143    fn check_instantiability(
144        _fn_spec: &FunctionSpecification,
145        _auth_ctx: &AuthorizationContext,
146        _args: &Vec<Type>,
147    ) -> Result<Type, Diagnostic> {
148        unimplemented!()
149    }
150
151    fn run(
152        fn_spec: &FunctionSpecification,
153        _auth_ctx: &AuthorizationContext,
154        args: &Vec<Value>,
155    ) -> Result<Value, Diagnostic> {
156        arg_checker(fn_spec, args)?;
157        let value = args.get(0).unwrap().as_string().unwrap().to_string();
158        let hash = keccak(value.as_bytes());
159        Ok(StdValue::hash(hash.0.to_vec()))
160    }
161}