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

first cut at having some control over what appears in the dispatch table #435

Closed
wants to merge 1 commit into from
Closed
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
26 changes: 22 additions & 4 deletions src/main/scala/edu/cmu/cs/obsidian/codegen/CodeGenYul.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,35 @@ object CodeGenYul extends CodeGenerator {
}
}

/** return true iff the declaration passed ought to be included in the dispatch table
* @param d
* @return
*/
def writeInDispatch(d : Declaration) : Boolean = {
d match {
case declaration: InvokableDeclaration => declaration match {
case Constructor(name, args, resultType, body) => false // constructors cannot be called from the outside
// todo: for now we omit private transactions and constructors only, but this can change over time.
case Transaction(name, params, args, retType, ensures, body, isStatic, isPrivate, thisType, thisFinalType, initialFieldTypes, finalFieldTypes) => ! isPrivate
}
case TypeDecl(name, typ) => false
case Field(isConst, typ, name, availableIn) => false
case State(name, fields, isAsset) => false
case contract: Contract => false
}
}

/** given a contract,
* translate all the declarations it contains into yul and produce that sequence and
* produce a default constructor for it if it does not have any constructors.
*
* @param c the contract to translate
* @return the sequence of yul statements for each declaration in the contract
* @return the sequence of yul statements for each declaration in the contract paired with a boolean that says if each should be included in the dispatch table
*/
def translateContract(c: Contract): Seq[YulStatement] = {
def translateContract(c: Contract): Seq[(YulStatement, Boolean)] = {
c match {
case _: ObsidianContractImpl =>
defaultConstructor(c) ++ c.declarations.flatMap(d => translateDeclaration(d, c.name, checkedTable))
defaultConstructor(c).map(d => (d, false)) ++ c.declarations.map(d => (translateDeclaration(d, c.name, checkedTable).head, writeInDispatch(d)))
case _: JavaFFIContractImpl =>
throw new RuntimeException("Java contract not supported in yul translation")
}
Expand All @@ -122,7 +140,7 @@ object CodeGenYul extends CodeGenerator {
mainConstructorTypeNames = defaultConstructorSignature(main_contract, checkedTable, ""),
// todo: this includes all of the default constructors in the top
defaultCons = (main_contract +: other_contracts).map(c => writeDefaultConstructor(c, checkedTable)),
otherTransactions = other_contracts.flatMap(translateContract),
otherTransactions = other_contracts.flatMap(translateContract).map(p => p._1),
tracers = (main_contract +: other_contracts).flatMap(c => writeTracers(checkedTable, c.name)).distinctBy(fd => fd.name)
)
}
Expand Down
16 changes: 8 additions & 8 deletions src/main/scala/edu/cmu/cs/obsidian/codegen/yulAST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ case class StringLiteral(content: String) extends YulAST
*/
case class YulObject(contractName: String,
data: Seq[Data],
mainContractTransactions: Seq[YulStatement],
mainContractTransactions: Seq[(YulStatement,Boolean)],
mainContractSize: Int,
mainConstructorTypeNames: Seq[TypedName],
defaultCons: Seq[YulStatement],
Expand Down Expand Up @@ -399,29 +399,29 @@ case class YulObject(contractName: String,
// result from the transaction definitions WITHOUT the `this` argument.
def dispatchTable(): codegen.Switch =
codegen.Switch(Identifier("selector"),
mainContractTransactions.map(t => codegen.Case(hexlit(hashOfFunctionDef(dropThisArgument(t.asInstanceOf[FunctionDefinition]))),
Block(dispatchEntry(t.asInstanceOf[FunctionDefinition])))))
mainContractTransactions.filter(p => p._2).map(t => codegen.Case(hexlit(hashOfFunctionDef(dropThisArgument(t._1.asInstanceOf[FunctionDefinition]))),
Block(dispatchEntry(t._1.asInstanceOf[FunctionDefinition])))))

// traverse the transactions and compute the abi functions we need to emit.
def abiEncodeTupleFuncs(): YulStatement = Block(
LineComment("abi encode tuple functions") +:
(mainContractTransactions ++ otherTransactions)
(mainContractTransactions.map(p => p._1) ++ otherTransactions)
.map(t => t.asInstanceOf[FunctionDefinition].returnVariables.length)
.distinct
.map(write_abi_encode_tuple_from_stack))

def abiDecodeFuncs(): YulStatement = Block(
LineComment("abi decode functions") +:
(// for each transaction, emit the decoder for the tuple of its arguments
(mainContractTransactions.map(t => write_abi_decode_tuple(dropThisArgument(t.asInstanceOf[FunctionDefinition]))).distinct
(mainContractTransactions.map(t => write_abi_decode_tuple(dropThisArgument(t._1.asInstanceOf[FunctionDefinition]))).distinct
// for each transaction, collect up the types that it uses, and then emit the decodes for those types
++ mainContractTransactions.flatMap(t => dropThisArgument(t.asInstanceOf[FunctionDefinition]).parameters.map(tn => tn.typ)).distinct.map(write_abi_decode)
++ mainContractTransactions.flatMap(t => dropThisArgument(t._1.asInstanceOf[FunctionDefinition]).parameters.map(tn => tn.typ)).distinct.map(write_abi_decode)
).distinct
)
)

def transactions(): YulStatement = Block(LineComment("translated transactions") +: (mainContractTransactions ++ otherTransactions))
def transactions(): YulStatement = Block(LineComment("translated transactions") +: (mainContractTransactions.map(p => p._1) ++ otherTransactions))

def tracertransactions(): YulStatement = Block(LineComment("per contract generated tracers") +: tracers)
def tracertransxactions(): YulStatement = Block(LineComment("per contract generated tracers") +: tracers)
}
}