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

Clarity Value Serialization and Name String Guarding #1099

Merged
merged 21 commits into from
Sep 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
12f0a8a
types.rs -> types/mod.rs
kantai Aug 19, 2019
f5f5961
Merge branch 'feature/general-cleanup' into feature/clarity-serializa…
kantai Aug 20, 2019
53a7bec
Merge remote-tracking branch 'origin/develop' into feature/clarity-se…
kantai Aug 20, 2019
0ac9a33
serializationclarity object serialization using our own impl of seria…
kantai Aug 21, 2019
2cc76f3
use expected types from the clarity_db to deserialize lists, tuples. …
kantai Aug 21, 2019
218be3f
refactor list typesignature, do type enforcement on value constructor…
kantai Aug 21, 2019
c5c2169
simple test for making sure get_value is setting max_len correctly on…
kantai Aug 21, 2019
ca1045b
serialization/deserialization code tests
kantai Aug 21, 2019
0e2a5f3
support deserializing with and without an expected_type.
kantai Aug 22, 2019
9d7425b
some light refactor, dead code removal from types module
kantai Aug 22, 2019
83db5da
more dead code removal, add test for contract-caller behavior
kantai Aug 22, 2019
3eaa70f
use our own hex serialization
kantai Aug 22, 2019
0d1e6a4
first steps toward guarded strings
kantai Aug 23, 2019
22dc81b
use guarded contractname type to represent contract names.
kantai Aug 25, 2019
21bc87a
use ClarityName in function args, ContractAnalysis
kantai Aug 26, 2019
32d50fe
a bit more restrictive regexes on the guarded strings
kantai Aug 26, 2019
36fdfc5
Added guarded strings to this branch. Merge branch 'feature/guarded-s…
kantai Aug 26, 2019
5742328
more dead code removal
kantai Aug 26, 2019
ce3b289
use ListTypeData::new() for list type construction. allow size of NoT…
kantai Aug 26, 2019
74257cd
only allow punction to start a name in native functions
kantai Sep 4, 2019
1297e42
use single & refs instead of double refs
kantai Sep 10, 2019
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
40 changes: 21 additions & 19 deletions src/vm/analysis/build_contract_interface/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use vm::analysis::types::ContractAnalysis;
use std::collections::{BTreeMap, BTreeSet};
use vm::{ClarityName};
use vm::types::{TypeSignature, FunctionArg, AtomTypeIdentifier, TupleTypeSignature, FunctionType};

pub fn build_contract_interface(contract_analysis: &ContractAnalysis) -> ContractInterface {
Expand All @@ -16,41 +17,42 @@ pub fn build_contract_interface(contract_analysis: &ContractAnalysis) -> Contrac
non_fungible_tokens,
top_level_expression_sorting: _,
expressions: _,
type_map: _,
} = contract_analysis;

contract_interface.functions.append(
&mut ContractInterfaceFunction::from_map(
&private_function_types,
private_function_types,
ContractInterfaceFunctionAccess::private));

contract_interface.functions.append(
&mut ContractInterfaceFunction::from_map(
&public_function_types,
public_function_types,
ContractInterfaceFunctionAccess::public));

contract_interface.functions.append(
&mut ContractInterfaceFunction::from_map(
&contract_analysis.read_only_function_types,
read_only_function_types,
ContractInterfaceFunctionAccess::read_only));

contract_interface.variables.append(
&mut ContractInterfaceVariable::from_map(
&variable_types,
variable_types,
ContractInterfaceVariableAccess::constant));

contract_interface.variables.append(
&mut ContractInterfaceVariable::from_map(
&persisted_variable_types,
persisted_variable_types,
ContractInterfaceVariableAccess::variable));

contract_interface.maps.append(
&mut ContractInterfaceMap::from_map(&map_types));
&mut ContractInterfaceMap::from_map(map_types));

contract_interface.non_fungible_tokens.append(
&mut ContractInterfaceNonFungibleTokens::from_map(&non_fungible_tokens));
&mut ContractInterfaceNonFungibleTokens::from_map(non_fungible_tokens));

contract_interface.fungible_tokens.append(
&mut ContractInterfaceFungibleTokens::from_set(&fungible_tokens));
&mut ContractInterfaceFungibleTokens::from_set(fungible_tokens));

contract_interface
}
Expand Down Expand Up @@ -142,9 +144,9 @@ impl ContractInterfaceAtomType {
TypeSignature::Atom(atom_type) => {
Self::from_atom_type(atom_type)
},
TypeSignature::List(atom_type, list_data) => {
TypeSignature::List(list_data) => {
ContractInterfaceAtomType::list {
type_f: Box::new(Self::from_atom_type(atom_type)),
type_f: Box::new(Self::from_atom_type(&list_data.atomic_type)),
length: list_data.max_len,
dimension: list_data.dimension
}
Expand Down Expand Up @@ -188,10 +190,10 @@ pub struct ContractInterfaceFunction {
}

impl ContractInterfaceFunction {
pub fn from_map(map: &BTreeMap<String, FunctionType>, access: ContractInterfaceFunctionAccess) -> Vec<ContractInterfaceFunction> {
pub fn from_map(map: &BTreeMap<ClarityName, FunctionType>, access: ContractInterfaceFunctionAccess) -> Vec<ContractInterfaceFunction> {
map.iter().map(|(name, function_type)| {
ContractInterfaceFunction {
name: name.to_string(),
name: name.clone().into(),
access: access.to_owned(),
outputs: ContractInterfaceFunctionOutput {
type_f: match function_type {
Expand Down Expand Up @@ -229,26 +231,26 @@ pub struct ContractInterfaceVariable {
}

impl ContractInterfaceFungibleTokens {
pub fn from_set(tokens: &BTreeSet<String>) -> Vec<Self> {
pub fn from_set(tokens: &BTreeSet<ClarityName>) -> Vec<Self> {
tokens.iter().map(|name| Self { name: name.to_string() }).collect()
}
}

impl ContractInterfaceNonFungibleTokens {
pub fn from_map(assets: &BTreeMap<String, TypeSignature>) -> Vec<Self> {
pub fn from_map(assets: &BTreeMap<ClarityName, TypeSignature>) -> Vec<Self> {
assets.iter().map(|(name, type_sig)|
Self {
name: name.to_string(),
name: name.clone().into(),
type_f: ContractInterfaceAtomType::from_type_signature(type_sig)
}).collect()
}
}

impl ContractInterfaceVariable {
pub fn from_map(map: &BTreeMap<String, TypeSignature>, access: ContractInterfaceVariableAccess) -> Vec<ContractInterfaceVariable> {
pub fn from_map(map: &BTreeMap<ClarityName, TypeSignature>, access: ContractInterfaceVariableAccess) -> Vec<ContractInterfaceVariable> {
map.iter().map(|(name, type_sig)| {
ContractInterfaceVariable {
name: name.to_string(),
name: name.clone().into(),
access: access.to_owned(),
type_f: ContractInterfaceAtomType::from_type_signature(type_sig),
}
Expand All @@ -264,7 +266,7 @@ pub struct ContractInterfaceMap {
}

impl ContractInterfaceMap {
pub fn from_map(map: &BTreeMap<String, (TypeSignature, TypeSignature)>) -> Vec<ContractInterfaceMap> {
pub fn from_map(map: &BTreeMap<ClarityName, (TypeSignature, TypeSignature)>) -> Vec<ContractInterfaceMap> {
map.iter().map(|(name, (key_sig, val_sig))| {

let key_type = match key_sig {
Expand All @@ -278,7 +280,7 @@ impl ContractInterfaceMap {
};

ContractInterfaceMap {
name: name.to_string(),
name: name.clone().into(),
key: key_type,
value: val_type,
}
Expand Down
10 changes: 5 additions & 5 deletions src/vm/analysis/definition_sorter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::{HashSet, HashMap};
use std::iter::FromIterator;
use vm::representations::{SymbolicExpression};
use vm::representations::{SymbolicExpression, ClarityName};
use vm::representations::SymbolicExpressionType::{AtomValue, Atom, List};
use vm::functions::NativeFunctions;
use vm::functions::define::DefineFunctions;
Expand All @@ -14,7 +14,7 @@ mod tests;

pub struct DefinitionSorter {
graph: Graph,
top_level_expressions_map: HashMap<String, TopLevelExpressionIndex>
top_level_expressions_map: HashMap<ClarityName, TopLevelExpressionIndex>
}

impl AnalysisPass for DefinitionSorter {
Expand Down Expand Up @@ -58,11 +58,11 @@ impl <'a> DefinitionSorter {
let sorted_indexes = walker.get_sorted_dependencies(&self.graph)?;

if let Some(deps) = walker.get_cycling_dependencies(&self.graph, &sorted_indexes) {
let deps_props: Vec<(String, u64, &SymbolicExpression)> = deps.iter().map(|i| {
let deps_props: Vec<(_)> = deps.iter().map(|i| {
let exp = &contract_analysis.expressions[*i];
self.find_expression_definition(&exp).unwrap()
}).collect();
let functions_names = deps_props.iter().map(|i| i.0.clone()).collect();
let functions_names = deps_props.iter().map(|i| i.0.to_string()).collect();
let exprs = deps_props.iter().map(|i| i.2.clone()).collect();

let mut error = CheckError::new(CheckErrors::CircularReference(functions_names));
Expand Down Expand Up @@ -194,7 +194,7 @@ impl <'a> DefinitionSorter {
}


fn find_expression_definition<'b>(&mut self, exp: &'b SymbolicExpression) -> Option<(String, u64, &'b SymbolicExpression)> {
fn find_expression_definition<'b>(&mut self, exp: &'b SymbolicExpression) -> Option<(ClarityName, u64, &'b SymbolicExpression)> {
let (_define_type, args) = DefineFunctions::try_parse(exp)?;
let defined_name = match args.get(0)?.match_list() {
Some(list) => list.get(0)?,
Expand Down
8 changes: 7 additions & 1 deletion src/vm/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod build_contract_interface;

use self::types::{ContractAnalysis, AnalysisPass};
use vm::representations::{SymbolicExpression};
use vm::types::{TypeSignature};

pub use self::errors::{CheckResult, CheckError, CheckErrors};
pub use self::analysis_db::{AnalysisDatabase};
Expand All @@ -20,11 +21,16 @@ use self::read_only_checker::ReadOnlyChecker;
use self::type_checker::TypeChecker;

#[cfg(test)]
pub fn mem_type_check(snippet: &str) -> CheckResult<ContractAnalysis> {
pub fn mem_type_check(snippet: &str) -> CheckResult<(Option<TypeSignature>, ContractAnalysis)> {
use vm::parser::parse;
let mut contract = parse(snippet).unwrap();
let mut analysis_db = AnalysisDatabase::memory();
type_check(&":transient:", &mut contract, &mut analysis_db, false)
.map(|x| {
// return the first type result of the type checker
let first_type = x.type_map.as_ref().unwrap()
.get_type(&x.expressions[0]).cloned();
(first_type, x) })
}

// Legacy function
Expand Down
15 changes: 8 additions & 7 deletions src/vm/analysis/read_only_checker/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use vm::representations::{SymbolicExpression};
use vm::representations::{SymbolicExpression, ClarityName};
use vm::representations::SymbolicExpressionType::{AtomValue, Atom, List};
use vm::types::{AtomTypeIdentifier, TypeSignature, TupleTypeSignature, parse_name_type_pairs};
use vm::functions::NativeFunctions;
Expand All @@ -18,7 +18,7 @@ mod tests;

pub struct ReadOnlyChecker <'a, 'b> {
db: &'a mut AnalysisDatabase<'b>,
defined_functions: HashMap<String, bool>
defined_functions: HashMap<ClarityName, bool>
}

impl <'a, 'b> AnalysisPass for ReadOnlyChecker <'a, 'b> {
Expand Down Expand Up @@ -54,19 +54,20 @@ impl <'a, 'b> ReadOnlyChecker <'a, 'b> {
Ok(())
}

fn check_define_function(&mut self, args: &[SymbolicExpression]) -> CheckResult<(String, bool)> {
fn check_define_function(&mut self, args: &[SymbolicExpression]) -> CheckResult<(ClarityName, bool)> {
check_argument_count(2, args)?;

let signature = args[0].match_list()
.ok_or(CheckErrors::DefineFunctionBadSignature)?;
let body = &args[1];

let (function_name, _) = signature.split_first()
.ok_or(CheckErrors::DefineFunctionBadSignature)?;
let function_name = signature.get(0)
.ok_or(CheckErrors::DefineFunctionBadSignature)?
.match_atom().ok_or(CheckErrors::BadFunctionName)?;

let is_read_only = self.is_read_only(body)?;

Ok((function_name.to_string(), is_read_only))
Ok((function_name.clone(), is_read_only))
}

fn check_reads_only_valid(&mut self, expr: &SymbolicExpression) -> CheckResult<()> {
Expand Down Expand Up @@ -248,7 +249,7 @@ impl <'a, 'b> ReadOnlyChecker <'a, 'b> {
result
} else {
let is_function_read_only = self.defined_functions.get(function_name)
.ok_or(CheckErrors::UnknownFunction(function_name.clone()))?
.ok_or(CheckErrors::UnknownFunction(function_name.to_string()))?
.clone();
self.are_all_read_only(is_function_read_only, args)
}
Expand Down
Loading