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

call the tracer after field writes #430

Merged
merged 42 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
fcc8b48
first pass at including default constructors
ivoysey Feb 22, 2022
7b73183
adding a time string to the benchmarks file so it doesn't get overwri…
ivoysey Feb 23, 2022
3ab6153
updating the test script to optionally save the optimized and pretty …
ivoysey Feb 23, 2022
abceaf7
generate constructor and arguments
ivoysey Feb 23, 2022
88ef611
changing the name of the test transaction to avoid #424
ivoysey Feb 24, 2022
003d764
adding a prefix to constructor argument names so that they are unique
ivoysey Feb 24, 2022
7729490
whitespace, scala style
ivoysey Feb 24, 2022
a605547
writing a helper for unified names of transactions
ivoysey Feb 24, 2022
885c362
updating codegen to use the single helper, adding comments
ivoysey Feb 24, 2022
a5822f3
convenience script for local debugging
ivoysey Feb 24, 2022
50337af
updating translateTransaction to be able to use the unified helper fo…
ivoysey Feb 24, 2022
392a0d1
fixing whitespace
ivoysey Feb 24, 2022
7fae856
changing the test script so that it calls transactions from main with…
ivoysey Feb 24, 2022
16b1e19
removing inMain boolean argument, it was a symptom of nonuniform tran…
ivoysey Feb 24, 2022
81e245d
removing some redunant code in translateProgram, pushing helpers into…
ivoysey Feb 25, 2022
eda226c
fixing a silly error, changing how line comments get printed for read…
ivoysey Feb 25, 2022
c08ecf4
first pass at producing the sequence of assignments for the body of t…
ivoysey Feb 25, 2022
fb721f6
whitespace, scala style
ivoysey Feb 25, 2022
ec0f303
some comments, changing the signature of the internal function so i c…
ivoysey Feb 25, 2022
4ab700e
removing an accidental implementation of seq.reverse
ivoysey Feb 25, 2022
9922108
updating helper script
ivoysey Feb 25, 2022
f38ab2d
update the field where it actually is in memory; adding a helper func…
ivoysey Feb 25, 2022
d281f5b
using the helper to declare vars not just assign them
ivoysey Feb 25, 2022
2813fa8
adding a test specifically for default constructors
ivoysey Feb 25, 2022
5fcb6ae
whitespace
ivoysey Feb 25, 2022
94e69a4
another missing reverse here
ivoysey Feb 25, 2022
260e466
adding comments
ivoysey Feb 25, 2022
f97fd39
first cut at calling the constructor for main per #426 #427
ivoysey Feb 25, 2022
76653ce
merge conflicts
ivoysey Feb 28, 2022
feed12a
comment
ivoysey Feb 28, 2022
fbb51d0
adding memory allocation to the invoke block, calling default constru…
ivoysey Mar 1, 2022
f152e16
moving the codecopy after the tracer def and call
ivoysey Mar 2, 2022
0553c81
adding a test case
ivoysey Mar 3, 2022
cc15501
scraps
ivoysey Mar 9, 2022
219e681
first cut at tracing after pointer write
ivoysey Mar 9, 2022
8d0ee22
merging in from master
ivoysey Mar 29, 2022
c4885b6
adding a couple new helper functions; changing the update field helpe…
ivoysey Mar 31, 2022
f6572b1
using new helper functions. adding tracer call code in pointer writes
ivoysey Mar 31, 2022
ee9728b
reversing a bad change, adding a comment about why so i dont feel tem…
ivoysey Mar 31, 2022
f73f979
after debugging, changing which identifier goes to the trace call
ivoysey Apr 1, 2022
1a91b63
whitespace, comments
ivoysey Apr 1, 2022
704f143
Removing trace this test case. see #434
ivoysey Apr 1, 2022
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
5 changes: 0 additions & 5 deletions resources/tests/GanacheTests/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,6 @@
"expected": "5743",
"deploy_logged" : [-57896044618658097711785492504343953926634992332820282019728792003956564819808,5738],
"shows_that_we_support": "default constructors + values get written to storage and resurrected on subsequent calls"
},
{
"file": "TraceThis.obs",
"expected": "-2438",
"shows_that_we_support": "emitting tracers and default constructors for more complicated nestings of objects. note that this emits 30 log messages between deployment and invocation; they look right but haven't been checked carefully"
}
]
}
42 changes: 34 additions & 8 deletions src/main/scala/edu/cmu/cs/obsidian/codegen/CodeGenYul.scala
Original file line number Diff line number Diff line change
Expand Up @@ -450,13 +450,39 @@ object CodeGenYul extends CodeGenerator {
val id = nextTemp()
val e_yul = translateExpr(id, e, contractName, checkedTable)
val ct = checkedTable.contractLookup(contractName)
decl_0exp(id) +:
e_yul :+
(if (ct.allFields.exists(f => f.name.equals(x))) {
updateField(ct, x, id)

val field_address = fieldFromThis(ct, x)

// look at assignTo. if it's a storage address, then look at the type of e.
// if it's a primitive, ignore it. if it's a contract reference, it needs
// to get traced first
val trace_for_e: Seq[YulStatement] = e.obstype match {
case Some(value) => value match {
case _: PrimitiveType => Seq()
case t: NonPrimitiveType => t match {
case ContractReferenceType(contractType, _, _) => // todo
Seq(
edu.cmu.cs.obsidian.codegen.If(apply("not", compareToThresholdExp(field_address)),
Block(Do(apply(nameTracer(contractType.contractName), id))))
)
case StateType(_, _, _) => assert(assertion = false, "not yet implemented"); Seq()
case InterfaceContractType(_, _) => assert(assertion = false, "not yet implemented"); Seq()
case GenericType(_, _) => assert(assertion = false, "not yet implemented"); Seq()
}
case BottomType() => Seq()
}
case None => assert(assertion = false, "encountered an expression without a type annotation"); Seq()
}

val update_instructions: Seq[YulStatement] =
if (ct.allFields.exists(f => f.name.equals(x))) {
trace_for_e :+ updateField(ct, x, id)
} else {
assign1(Identifier(x), id)
})
Seq(assign1(Identifier(x), id))
}

decl_0exp(id) +: (e_yul ++ update_instructions)

case _ =>
assert(assertion = false, "trying to assign to non-assignable: " + e.toString)
Seq()
Expand Down Expand Up @@ -614,7 +640,7 @@ object CodeGenYul extends CodeGenerator {
// here or not.
ids.map(id => decl_0exp(id)) ++
seqs.flatten ++ (width match {
case 0 => Seq(ExpressionStatement(FunctionCall(Identifier(name), thisID +: ids)))
case 0 => Do(FunctionCall(Identifier(name), thisID +: ids))
case 1 =>
val id: Identifier = nextTemp()
Seq(decl_1exp(id, FunctionCall(Identifier(name), thisID +: ids)), assign1(retvar, id))
Expand Down Expand Up @@ -747,7 +773,7 @@ object CodeGenYul extends CodeGenerator {
// we only call the tracer after the constructor for the main contract
val traceCall =
if (isMainContract) {
Seq(ExpressionStatement(apply(nameTracer(contractType.contractName), Identifier("this"))))
Do(apply(nameTracer(contractType.contractName), Identifier("this")))
} else {
Seq()
}
Expand Down
30 changes: 23 additions & 7 deletions src/main/scala/edu/cmu/cs/obsidian/codegen/Util.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ object Util {
* @return the yul if-statement doing the check
*/
def revertIf(cond: Expression): YulStatement =
edu.cmu.cs.obsidian.codegen.If(cond, Block(Seq(ExpressionStatement(apply("revert", intlit(0), intlit(0))))))
edu.cmu.cs.obsidian.codegen.If(cond, Block(Do(apply("revert", intlit(0), intlit(0)))))

/**
* @return the yul call value check statement, which makes sure that funds are not spent inappropriately
Expand All @@ -111,7 +111,7 @@ object Util {
* @return the yul if-statement doing the check
*/
def revertForwardIfZero(id: Expression): YulStatement =
edu.cmu.cs.obsidian.codegen.If(apply("iszero", id), Block(Seq(ExpressionStatement(apply("revert_forward_1")))))
edu.cmu.cs.obsidian.codegen.If(apply("iszero", id), Block(Do(apply("revert_forward_1"))))

/**
* shorthand for building yul assignment statements, here assigning one expression to just one
Expand Down Expand Up @@ -404,8 +404,8 @@ object Util {
def updateField(ct: ContractTable, fieldName: String, value: Expression): YulStatement = {
val address_of_field: Expression = fieldFromThis(ct, fieldName)
ifInStorge(addr_to_check = address_of_field,
true_case = Seq(ExpressionStatement(apply("sstore", address_of_field, value))),
false_case = Seq(ExpressionStatement(apply("mstore", address_of_field, value)))
true_case = Do(apply("sstore", address_of_field, value)), // todo double check why there isn't a mapToStorageAddr call here; i think it's because you only end up in this branch when `this` is already big enough
false_case = Do(apply("mstore", address_of_field, value))
)
}

Expand Down Expand Up @@ -595,6 +595,24 @@ object Util {
apply("add", x, storage_threshold)
}

/** the returned expression evaluates to true iff the argument is above or equal to the storage threshold
*
* @param addr
* @return
*/
def compareToThresholdExp(addr: Expression): Expression = {
apply("gt", addr, apply("sub", storage_threshold, intlit(1)))
}

/** convenience function for taking an expression and building a singleton statement sequence
*
* @param x
* @return
*/
def Do(x: Expression): Seq[YulStatement] = {
Seq(ExpressionStatement(x))
}

/** given an expression that represents an address, compute the yul statement that checks if it's
* a storage address or not and execute a sequence of statements in either case. if it does not
* represent an address, the behaviour is undefined.
Expand All @@ -606,7 +624,7 @@ object Util {
*/
def ifInStorge(addr_to_check: Expression, true_case: Seq[YulStatement], false_case: Seq[YulStatement]): YulStatement = {
// note: gt(x,y) is x > y; to get x >= y, subtract 1 since they're integers
edu.cmu.cs.obsidian.codegen.Switch(apply("gt", addr_to_check, apply("sub", storage_threshold, intlit(1))),
edu.cmu.cs.obsidian.codegen.Switch(compareToThresholdExp(addr_to_check),
Seq(Case(boollit(true), Block(true_case)),
Case(boollit(false), Block(false_case))))
}
Expand Down Expand Up @@ -650,6 +668,4 @@ object Util {
case YATContractName(name) => throw new RuntimeException("can't query for a default contract value")
}
}


}