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

Helper binary for viewing function selectors #141

Merged
merged 3 commits into from
Aug 17, 2021
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion core_lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ authors = ["Alex <[email protected]>"]
edition = "2018"
rust = "1.50"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
selector-debug = ["structopt", "hex"]

[dependencies]
#pest = "2.0"
Expand All @@ -19,3 +20,11 @@ uuid-b64 = "0.1"
fuel-asm = { git = "ssh://[email protected]/FuelLabs/fuel-asm.git" }
fuel-vm = { git = "ssh://[email protected]/FuelLabs/fuel-vm.git" }
sha2 = "0.9"
structopt = { version = "0.3", default-features = false, optional = true }
hex = { version = "0.4", optional = true }


[[bin]]
name = "selector-debug"
path = "utils/selector_debug.rs"
required-features = ["selector-debug"]
2 changes: 1 addition & 1 deletion core_lang/src/control_flow_analysis/flow_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) use namespace::FunctionNamespaceEntry;
pub type EntryPoint = NodeIndex;
pub type ExitPoint = NodeIndex;

#[derive(Clone)]
#[derive(Clone, Default)]
/// A graph that can be used to model the control flow of a fuel HLL program.
/// This graph is used as the basis for all of the algorithms in the control flow analysis portion
/// of the compiler.
Expand Down
8 changes: 4 additions & 4 deletions core_lang/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#[macro_use]
extern crate pest_derive;
#[macro_use]
mod error;
pub mod error;

mod asm_generation;
mod asm_lang;
mod build_config;
pub mod constants;
mod control_flow_analysis;
mod ident;
mod parse_tree;
pub mod parse_tree;
mod parser;
mod semantic_analysis;
pub mod semantic_analysis;

pub use crate::parse_tree::*;
pub use crate::parser::{HllParser, Rule};
Expand All @@ -22,7 +22,7 @@ use control_flow_analysis::{ControlFlowGraph, Graph};
use pest::iterators::Pair;
use pest::Parser;
use semantic_analysis::{TreeType, TypedParseTree};
pub(crate) mod types;
pub mod types;
pub(crate) mod utils;
pub use crate::parse_tree::{Declaration, Expression, UseStatement, WhileLoop};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct FunctionDeclaration<'sc> {
}

impl<'sc> FunctionDeclaration<'sc> {
pub(crate) fn parse_from_pair(pair: Pair<'sc, Rule>) -> CompileResult<'sc, Self> {
pub fn parse_from_pair(pair: Pair<'sc, Rule>) -> CompileResult<'sc, Self> {
let mut parts = pair.clone().into_inner();
let mut warnings = Vec::new();
let mut errors = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion core_lang/src/parse_tree/declaration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod abi_declaration;
mod enum_declaration;
mod function_declaration;
pub mod function_declaration;
mod impl_trait;
mod reassignment;
mod struct_declaration;
Expand Down
25 changes: 18 additions & 7 deletions core_lang/src/semantic_analysis/ast_node/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,7 @@ impl<'sc> TypedFunctionDeclaration<'sc> {
is_contract_call: self.is_contract_call,
}
}
/// Converts a [TypedFunctionDeclaration] into a value that is to be used in contract function
/// selectors.
/// Hashes the name and parameters using SHA256, and then truncates to four bytes.
pub(crate) fn to_fn_selector_value(&self) -> CompileResult<'sc, [u8; 4]> {
pub fn to_fn_selector_value_untruncated(&self) -> CompileResult<'sc, Vec<u8>> {
let mut errors = vec![];
let mut warnings = vec![];
let mut hasher = Sha256::new();
Expand All @@ -290,14 +287,28 @@ impl<'sc> TypedFunctionDeclaration<'sc> {
errors
);
hasher.update(data);
let hash = hasher.finalize();
ok(hash.to_vec(), warnings, errors)
}
/// Converts a [TypedFunctionDeclaration] into a value that is to be used in contract function
/// selectors.
/// Hashes the name and parameters using SHA256, and then truncates to four bytes.
pub fn to_fn_selector_value(&self) -> CompileResult<'sc, [u8; 4]> {
let mut errors = vec![];
let mut warnings = vec![];
let hash = type_check!(
self.to_fn_selector_value_untruncated(),
return err(warnings, errors),
warnings,
errors
);
// 4 bytes truncation via copying into a 4 byte buffer
let mut buf = [0u8; 4];
let hash = hasher.finalize();
buf.copy_from_slice(&hash[0..4]);
ok(buf, warnings, errors)
}

pub(crate) fn to_selector_name(&self) -> CompileResult<'sc, String> {
pub fn to_selector_name(&self) -> CompileResult<'sc, String> {
let mut errors = vec![];
let mut warnings = vec![];
let named_params = {
Expand Down Expand Up @@ -456,7 +467,7 @@ pub struct TypedReassignment<'sc> {
}

impl<'sc> TypedFunctionDeclaration<'sc> {
pub(crate) fn type_check(
pub fn type_check(
fn_decl: FunctionDeclaration<'sc>,
namespace: &Namespace<'sc>,
_return_type_annotation: Option<MaybeResolvedType<'sc>>,
Expand Down
2 changes: 1 addition & 1 deletion core_lang/src/semantic_analysis/ast_node/impl_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ pub(crate) fn implementation_of_trait<'sc>(
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum Mode {
pub enum Mode {
ImplAbiFn,
NonAbi,
}
Expand Down
4 changes: 2 additions & 2 deletions core_lang/src/semantic_analysis/ast_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use pest::Span;
use std::path::Path;

mod code_block;
mod declaration;
pub mod declaration;
mod expression;
mod impl_trait;
pub mod impl_trait;
mod return_statement;
mod while_loop;

Expand Down
2 changes: 1 addition & 1 deletion core_lang/src/semantic_analysis/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub(crate) mod ast_node;
pub mod ast_node;
mod namespace;
mod syntax_tree;
pub(crate) use ast_node::{TypedAstNode, TypedAstNodeContent, TypedExpression};
Expand Down
68 changes: 68 additions & 0 deletions core_lang/utils/selector_debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Used to debug function selectors
//! Given an input function declaration, return the selector for it in hexidecimal.
use pest::Parser;
use structopt::StructOpt;

use core_lang::{
error::CompileResult,
parse_tree::function_declaration::FunctionDeclaration,
semantic_analysis::ast_node::{declaration::TypedFunctionDeclaration, impl_trait::Mode},
types::{MaybeResolvedType, ResolvedType},
BuildConfig, HllParser, Rule,
};

#[derive(Debug, StructOpt)]
#[structopt(name = "example", about = "An example of StructOpt usage.")]
struct Opt {
fn_decl: String,
}

fn main() {
let opt = Opt::from_args();
let fn_decl = opt.fn_decl;

let parsed_fn_decl = HllParser::parse(Rule::fn_decl, &fn_decl);
let mut parsed_fn_decl = match parsed_fn_decl {
Ok(o) => o,
Err(e) => panic!("Failed to parse: {:?}", e),
};
let parsed_fn_decl = FunctionDeclaration::parse_from_pair(parsed_fn_decl.next().unwrap());
let parsed_fn_decl = match parsed_fn_decl {
CompileResult::Ok { value, .. } => value,
CompileResult::Err { errors, .. } => panic!("Failed to parse: {:?}", errors),
};

let res = match TypedFunctionDeclaration::type_check(
parsed_fn_decl,
&Default::default(),
None,
"",
&MaybeResolvedType::Resolved(ResolvedType::Unit),
&BuildConfig::root_from_manifest_path(Default::default()),
&mut Default::default(),
Mode::ImplAbiFn,
) {
CompileResult::Ok { value, .. } => value,
CompileResult::Err { errors, .. } => panic!("Failed to type check: {:?}", errors),
};

let selector_string = match res.to_selector_name() {
CompileResult::Ok { value, .. } => value,
CompileResult::Err { errors, .. } => {
panic!("Failed to construct selector name: {:?}", errors)
}
};
let selector_hash_untruncated = match res.to_fn_selector_value_untruncated() {
CompileResult::Ok { value, .. } => value,
CompileResult::Err { errors, .. } => panic!("Failed to construct hash: {:?}", errors),
};
let selector_hash_untruncated = hex::encode(selector_hash_untruncated);
let selector_hash = match res.to_fn_selector_value() {
CompileResult::Ok { value, .. } => value,
CompileResult::Err { errors, .. } => panic!("Failed to construct hash: {:?}", errors),
};
let selector_hash = hex::encode(selector_hash);
println!("selector string: {}", selector_string);
println!("untruncated hash: 0x{}", selector_hash_untruncated);
println!("truncated/padded hash: 0x00000000{}", selector_hash);
}