Skip to content

Commit

Permalink
Add tests expload#245
Browse files Browse the repository at this point in the history
  • Loading branch information
nevgeny committed Oct 17, 2018
1 parent c51d691 commit 18cf11a
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 41 deletions.
2 changes: 1 addition & 1 deletion evm/src/main/scala/pravda/evm/parse/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ object Parser {

private val ops: P[Either[String, List[Op]]] = P(Start ~ op.rep ~ End).map(ops => sequence(ops.toList))

val opsWithIndices = P(Start ~ (Index ~ op).rep ~ End)
val opsWithIndices = P(Start ~ (Index ~ op).rep ~ End)

}
36 changes: 26 additions & 10 deletions evm/src/main/scala/pravda/evm/translate/Translator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,35 @@ object Translator {
ops.map(SimpleTranslation.evmOpToOps).sequence.map(_.flatten)
}

def translateActualContract(ops: List[(Int,EVM.Op)]): Either[String, List[asm.Operation]] = {
val offsetEither = ops.takeWhile({case (_,CodeCopy) => false case _ => true}).reverse.tail.headOption match {
case Some((_,Push(address))) => Right(BigInt(1,address.toArray).intValue())
case _ => Left("Parse error")
def translateActualContract(ops: List[(Int, EVM.Op)]): Either[String, List[asm.Operation]] = {
val offsetEither = ops
.takeWhile({
case (_, CodeCopy) => false
case _ => true
})
.reverse
.tail
.headOption match {
case Some((_, Push(address))) => Right(BigInt(1, address.toArray).intValue())
case _ => Left("Parse error")
}

offsetEither.flatMap({offset =>
val filteredOps = ops.map({ case (ind, op) => ind - offset -> op }).filterNot(_._1 < 0).map({
case (ind,JumpDest) => JumpDest(ind)
case (_,op) => op
offsetEither.flatMap({ offset =>
val filteredOps = ops
.map({ case (ind, op) => ind - offset -> op })
.filterNot(_._1 < 0)
.map({
case (ind, JumpDest) => JumpDest(ind)
case (_, op) => op
})
val jumpDests = filteredOps.filter({
case JumpDest(_) => true
case _ => false
})
val jumpDests = filteredOps.filter({case JumpDest(_) => true case _ => false})
jumpDests.map(JumpDestinationPrepare.evmOpToOps).sequence.map(_.flatten)
jumpDests
.map(JumpDestinationPrepare.evmOpToOps)
.sequence
.map(_.flatten)
.flatMap(prepare => Translator(filteredOps).map(opcodes => prepare ++ opcodes))
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import pravda.vm.asm.Operation.PushRef

object JumpDestinationPrepare {


def evmOpToOps(op: EVM.Op): Either[String, List[asm.Operation]] =
op match {
case JumpDest(addr) => Right(List(PushRef(getNameByAddress(addr)),pushBigInt(BigInt(addr)),asm.Operation(Opcodes.SPUT)))
case JumpDest(addr) =>
Right(List(PushRef(getNameByAddress(addr)), pushBigInt(BigInt(-addr)), asm.Operation(Opcodes.SPUT)))
case _ => Left(s"Require JUMPDEST opcode, but found $op")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ object SimpleTranslation {
callExp,
codeToOps(Opcodes.SWAP),
codeToOps(Opcodes.DIV),
pushInt(0xff) :: Nil,
pushBigInt(0xff) :: Nil,
codeToOps(Opcodes.AND)
).flatten

Expand All @@ -73,8 +73,10 @@ object SimpleTranslation {
case Gt => codeToOps(Opcodes.GT) ::: cast(Data.Type.BigInt)
case Eq => codeToOps(Opcodes.EQ) ::: cast(Data.Type.BigInt)

case Jump => codeToOps(Opcodes.SGET) ::: Operation.Jump(None) :: Nil
case JumpI => codeToOps(Opcodes.SGET,Opcodes.SWAP) ::: cast(Data.Type.Boolean) ::: codeToOps(Opcodes.SWAP) ::: Operation.JumpI(None) :: Nil
case Jump => pushBigInt(BigInt(-1)) :: codeToOps(Opcodes.MUL, Opcodes.SGET) ::: Operation.Jump(None) :: Nil
case JumpI =>
pushBigInt(BigInt(-1)) :: codeToOps(Opcodes.MUL, Opcodes.SGET, Opcodes.SWAP) ::: cast(Data.Type.Boolean) ::: codeToOps(
Opcodes.SWAP) ::: Operation.JumpI(None) :: Nil
case Stop => codeToOps(Opcodes.STOP)

case Dup(n) => if (n > 1) dupn(n) else codeToOps(Opcodes.DUP)
Expand All @@ -84,6 +86,9 @@ object SimpleTranslation {
case Address => codeToOps(Opcodes.PADDR)

case JumpDest(address) => asm.Operation.Label(getNameByAddress(address)) :: Nil

case SStore => codeToOps(Opcodes.SPUT)
case SLoad => codeToOps(Opcodes.SGET)
}

def evmOpToOps(op: EVM.Op): Either[String, List[asm.Operation]] =
Expand Down
2 changes: 0 additions & 2 deletions evm/src/test/scala/pravda/evm/parse/EvmTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ object EvmTests extends TestSuite {
'SimpleStorage - {
val bytes = evm.readSolidityBinFile("SimpleStorage.bin")

Parser.opsWithIndices.parse(bytes).get.value.foreach(println)

Parser(bytes) ==>
Right(
List(
Expand Down
73 changes: 50 additions & 23 deletions evm/src/test/scala/pravda/evm/translate/opcode/EvaluateTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import pravda.evm._
import pravda.evm.EVM._
import pravda.evm.translate.Translator
import pravda.vm.Data.Primitive.BigInt
import pravda.vm.VmSandbox.EnvironmentEffect.{StorageGet, StoragePut}
import pravda.vm.VmSandbox.Preconditions
import utest._

Expand All @@ -16,7 +17,7 @@ object EvaluateTests extends TestSuite {
//FIXME when memory usage will be fixed. All tests will be incorrect
import SimpleTranslation._
import pravda.vm.Data.Primitive._
val precondition = Preconditions(balances = Map.empty, watts = 1000L)
val precondition = Preconditions(balances = Map.empty, watts = 1000L, executor = None)
"PUSH" - {
run(evmOpToOps(Push(hex"0x80")), precondition) ==> Right(
expectations(101L, stack = ArrayBuffer(BigInt(scala.BigInt(128)))))
Expand Down Expand Up @@ -115,16 +116,18 @@ object EvaluateTests extends TestSuite {
Right(expectations(108L, stack = ArrayBuffer(BigInt(expectation))))
}

//TODO test with "BYTE" when will be added exponential function
// "BYTE" - {
// val x = hex"0x426"
// val pos = hex"0x1f"
// println(x.last)
// val expectation = scala.BigInt(1,x.toArray)
//
// run(Translator(List(Push(x),Push(pos),Byte)),precondition)==>
// Right(expectations(108L,stack = ArrayBuffer(BigInt(expectation))))
// }
"BYTE" - {
val x = hex"0x426"
var pos = hex"0x1f"

run(Translator(List(Push(x), Push(pos), Byte)), precondition) ==>
Right(expectations(191L, stack = ArrayBuffer(BigInt(scala.BigInt(x.last.toInt)))))

pos = hex"0x1e"
val expectation = x.reverse.tail.head.toInt
run(Translator(List(Push(x), Push(pos), Byte)), precondition) ==>
Right(expectations(191L, stack = ArrayBuffer(BigInt(scala.BigInt(expectation)))))
}

"LT" - {
val x = hex"0x4"
Expand Down Expand Up @@ -156,11 +159,11 @@ object EvaluateTests extends TestSuite {
Right(expectations(120L, stack = ArrayBuffer(BigInt(scala.BigInt(1)))))
}

"JUMPDEST" - {
val `0` = hex"0x0"
val `1` = hex"0x1"
val `3` = hex"0x3"
val `4` = hex"0x4"
val `0` = hex"0x0"
val `1` = hex"0x1"
val `3` = hex"0x3"
val `4` = hex"0x4"
"JUMPS" - {

run(
Translator.translateActualContract(
Expand All @@ -175,10 +178,12 @@ object EvaluateTests extends TestSuite {
6 -> Push(`4`),
7 -> Push(`4`),
7 -> JumpDest,
))
,precondition).foreach({expect =>
expect.watts ==> 217L
expect.memory.stack ==> ArrayBuffer(BigInt(scala.BigInt(4)))
)),
precondition
).foreach({ expect =>
expect.watts ==> 229L
expect.memory.stack ==> ArrayBuffer(BigInt(scala.BigInt(4)))
expect.error ==> None
})

run(
Expand All @@ -195,13 +200,35 @@ object EvaluateTests extends TestSuite {
6 -> Push(`4`),
7 -> Push(`4`),
7 -> JumpDest,
))
,precondition).foreach({expect =>
expect.watts ==> 237L
)),
precondition
).foreach({ expect =>
expect.watts ==> 249L
expect.memory.stack ==> ArrayBuffer(BigInt(scala.BigInt(4)))
expect.error ==> None
})
}

"SSTORE SLOAD" - {

run(Translator(
List(
Push(`4`),
Push(`3`),
SStore,
Push(`3`),
SLoad
)
),
precondition).foreach({ expect =>
expect.watts ==> 193
expect.effects ==> ArrayBuffer(StoragePut(BigInt(scala.BigInt(3)), BigInt(scala.BigInt(4))),
StorageGet(BigInt(scala.BigInt(3)), Some(BigInt(scala.BigInt(4)))))
expect.memory.stack ==> ArrayBuffer(BigInt(scala.BigInt(4)))
expect.error ==> None
})
}

}

}

0 comments on commit 18cf11a

Please sign in to comment.