Skip to content

Commit c179559

Browse files
author
Grant Wuerker
committed
hacking
1 parent 797586f commit c179559

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+3458
-47
lines changed

Cargo.lock

+55-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ members = ["crates/*"]
55
opt-level = 3
66

77
[profile.dev]
8-
# Speeds up the build. May need to diable for debugging.
8+
# Speeds up the build. May need to disable for debugging.
99
debug = 0

crates/analyzer/src/db.rs

+2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ pub trait AnalyzerDb: SourceDb + Upcast<dyn SourceDb> + UpcastMut<dyn SourceDb>
110110
fn module_submodules(&self, module: ModuleId) -> Rc<[ModuleId]>;
111111
#[salsa::invoke(queries::module::module_tests)]
112112
fn module_tests(&self, module: ModuleId) -> Vec<FunctionId>;
113+
#[salsa::invoke(queries::module::module_invariants)]
114+
fn module_invariants(&self, module: ModuleId) -> Vec<FunctionId>;
113115

114116
// Module Constant
115117
#[salsa::cycle(queries::module::module_constant_type_cycle)]

crates/analyzer/src/db/queries/module.rs

+9
Original file line numberDiff line numberDiff line change
@@ -760,3 +760,12 @@ pub fn module_tests(db: &dyn AnalyzerDb, ingot: ModuleId) -> Vec<FunctionId> {
760760
.filter(|function| function.is_test(db))
761761
.collect()
762762
}
763+
764+
pub fn module_invariants(db: &dyn AnalyzerDb, ingot: ModuleId) -> Vec<FunctionId> {
765+
ingot
766+
.all_functions(db)
767+
.iter()
768+
.copied()
769+
.filter(|function| function.is_invariant(db))
770+
.collect()
771+
}

crates/analyzer/src/namespace/items.rs

+11
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,10 @@ impl ModuleId {
555555
db.module_tests(*self)
556556
}
557557

558+
pub fn invariants(&self, db: &dyn AnalyzerDb) -> Vec<FunctionId> {
559+
db.module_invariants(*self)
560+
}
561+
558562
/// Returns `true` if the `item` is in scope of the module.
559563
pub fn is_in_scope(&self, db: &dyn AnalyzerDb, item: Item) -> bool {
560564
if let Some(val) = item.module(db) {
@@ -1351,6 +1355,13 @@ impl FunctionId {
13511355
.iter()
13521356
.any(|attribute| attribute.name(db) == "test")
13531357
}
1358+
1359+
pub fn is_invariant(&self, db: &dyn AnalyzerDb) -> bool {
1360+
Item::Function(*self)
1361+
.attributes(db)
1362+
.iter()
1363+
.any(|attribute| attribute.name(db) == "invariant")
1364+
}
13541365
}
13551366

13561367
trait FunctionsAsItems {

crates/codegen/src/yul/isel/function.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,8 @@ impl<'db, 'a> FuncLowerHelper<'db, 'a> {
668668
debug_assert!(to.is_primitive(self.db.upcast()));
669669

670670
let value = self.value_expr(value);
671-
self.ctx.runtime.primitive_cast(self.db, value, from_ty)
671+
// self.ctx.runtime.primitive_cast(self.db, value, from_ty)
672+
value
672673
}
673674

674675
fn assign_inst_result(&mut self, inst: InstId, rhs: yul::Expression, rhs_ty: TypeId) {

crates/codegen/src/yul/isel/test.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,21 @@ pub fn lower_test(db: &dyn CodegenDb, test: FunctionId) -> yul::Object {
2222
.map(yul::Statement::FunctionDefinition)
2323
.collect();
2424
let test_func_name = identifier! { (db.codegen_function_symbol_name(test)) };
25-
let call = function_call_statement! {[test_func_name]()};
25+
let call_args = test
26+
.signature(db.upcast())
27+
.params
28+
.iter()
29+
.enumerate()
30+
.filter_map(|(n, param)| {
31+
if param.name == "ctx" {
32+
None
33+
} else {
34+
let value = literal_expression! { (n * 32) };
35+
Some(expression! { calldataload([value]) })
36+
}
37+
})
38+
.collect::<Vec<_>>();
39+
let call = function_call_statement! {[test_func_name]([call_args...])};
2640

2741
let code = code! {
2842
[dep_functions...]

crates/codegen/src/yul/runtime/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ pub trait RuntimeProvider {
163163
expression! { signextend([significant], [value]) }
164164
} else {
165165
let mask = BitMask::new(from_size);
166-
expression! { and([value], [mask.as_expr()]) }
166+
// expression! { and([value], [mask.as_expr()]) }
167+
value
167168
}
168169
}
169170

crates/driver/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ fe-codegen = {path = "../codegen", version = "^0.22.0"}
2020
fe-parser = {path = "../parser", version = "^0.22.0"}
2121
fe-yulc = {path = "../yulc", version = "^0.22.0", features = ["solc-backend"], optional = true}
2222
fe-test-runner = {path = "../test-runner", version = "^0.22.0"}
23+
fe-proof-service = {path = "../proof-service", version = "^0.22.0"}
2324
indexmap = "1.6.2"
2425
vfs = "0.5.1"
2526
smol_str = "0.1.21"

crates/driver/src/lib.rs

+39
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use fe_common::db::Upcast;
77
use fe_common::diagnostics::Diagnostic;
88
use fe_common::files::FileKind;
99
use fe_parser::ast::SmolStr;
10+
use fe_proof_service::invariant::Invariant;
1011
use fe_test_runner::TestSink;
1112
use indexmap::{indexmap, IndexMap};
1213
use serde_json::Value;
@@ -86,6 +87,23 @@ pub fn compile_single_file_tests(
8687
}
8788
}
8889

90+
#[cfg(feature = "solc-backend")]
91+
pub fn compile_single_file_invariants(
92+
db: &mut Db,
93+
path: &str,
94+
src: &str,
95+
optimize: bool,
96+
) -> Result<Vec<Invariant>, CompileError> {
97+
let module = ModuleId::new_standalone(db, path, src);
98+
let diags = module.diagnostics(db);
99+
100+
if diags.is_empty() {
101+
Ok(compile_module_invariants(db, module, optimize))
102+
} else {
103+
Err(CompileError(diags))
104+
}
105+
}
106+
89107
// Run analysis with ingot
90108
// Return vector error,waring...
91109
pub fn check_ingot(
@@ -196,6 +214,7 @@ fn compile_test(db: &mut Db, test: FunctionId, optimize: bool) -> CompiledTest {
196214
let yul_test = fe_codegen::yul::isel::lower_test(db, test)
197215
.to_string()
198216
.replace('"', "\\\"");
217+
// panic!("{}", yul_test);
199218
let bytecode = compile_to_evm("test", &yul_test, optimize);
200219
CompiledTest::new(test.name(db), bytecode)
201220
}
@@ -209,6 +228,26 @@ fn compile_module_tests(db: &mut Db, module_id: ModuleId, optimize: bool) -> Vec
209228
.collect()
210229
}
211230

231+
#[cfg(feature = "solc-backend")]
232+
fn compile_module_invariants(db: &mut Db, module_id: ModuleId, optimize: bool) -> Vec<Invariant> {
233+
use fe_proof_service::invariant::Invariant;
234+
235+
module_id
236+
.invariants(db)
237+
.iter()
238+
.map(|test| {
239+
let args = test
240+
.signature(db)
241+
.params
242+
.iter()
243+
.map(|param| param.typ.as_ref().unwrap().name(db))
244+
.collect();
245+
let test = compile_test(db, *test, optimize);
246+
Invariant::new(test.name, args, test.bytecode)
247+
})
248+
.collect()
249+
}
250+
212251
#[cfg(feature = "solc-backend")]
213252
fn compile_module(
214253
db: &mut Db,

crates/fe/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ fe-test-runner = {path = "../test-runner", version = "^0.22.0"}
2424
fe-common = {path = "../common", version = "^0.22.0"}
2525
fe-driver = {path = "../driver", version = "^0.22.0"}
2626
fe-parser = {path = "../parser", version = "^0.22.0"}
27+
fe-proof-service = {path = "../proof-service", version = "^0.22.0"}
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use std::spec
2+
use std::evm
3+
4+
#invariant
5+
fn de_morgan_true(a: bool, b: bool) {
6+
spec::given_true(a and b)
7+
spec::assert_true(not ((not a) or (not b)))
8+
}
9+
10+
#invariant
11+
fn de_morgan_false(a: bool, b: bool) {
12+
spec::given_false(a and b)
13+
spec::assert_false(not ((not a) or (not b)))
14+
}
15+
16+
#invariant
17+
fn shl_shr_248(a: u256) {
18+
spec::given_lte(a, 255)
19+
20+
let shl_a: u256 = evm::shl(bits: 248, value: a)
21+
spec::assert_eq(
22+
a,
23+
evm::shr(bits: 248, value: shl_a)
24+
)
25+
}
26+
27+
#invariant
28+
fn shl_shr_n(a: u256, n: u256) {
29+
spec::given_lte(a, 255)
30+
spec::given_lte(n, 248)
31+
32+
let shl_a: u256 = evm::shl(bits: n, value: a)
33+
spec::assert_eq(
34+
a,
35+
evm::shr(bits: n, value: shl_a)
36+
)
37+
}
38+
39+
const FREE_MEM_PTR: u256 = 4096
40+
41+
#invariant
42+
unsafe fn read_byte_shl_248(a: u8) {
43+
evm::mstore(
44+
offset: FREE_MEM_PTR,
45+
value: evm::shl(bits: 248, value: a)
46+
)
47+
48+
spec::assert_eq(
49+
a,
50+
evm::shr(bits: 248, value: evm::mload(offset: FREE_MEM_PTR))
51+
)
52+
}
53+
54+
// #invariant
55+
// incomplete
56+
// unsafe fn read_byte_mstore8(a: u8) {
57+
// evm::mstore8(offset: FREE_MEM_PTR, value: a)
58+
59+
// spec::assert_eq(
60+
// a,
61+
// evm::shr(bits: 248, value: evm::mload(offset: FREE_MEM_PTR))
62+
// )
63+
// }

0 commit comments

Comments
 (0)