Skip to content

Commit ad6040e

Browse files
committed
Merge remote-tracking branch 'origin/feature/mallet' into phase/iele_testnet
2 parents 491b2af + 3da9694 commit ad6040e

28 files changed

+1288
-104
lines changed

build.sbt

Lines changed: 10 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -50,106 +50,15 @@ val dep = {
5050
// Pluggable Consensus: AtomixRaft
5151
"io.atomix" % "atomix" % "2.1.0-beta1",
5252
"io.atomix" % "atomix-raft" % "2.1.0-beta1",
53-
"io.netty" % "netty-tcnative-boringssl-static" % "2.0.7.Final" classifier "linux-x86_64" // using native epoll
53+
"io.netty" % "netty-tcnative-boringssl-static" % "2.0.7.Final" classifier "linux-x86_64", // using native epoll
54+
55+
// mallet deps
56+
"org.jline" % "jline" % "3.1.2",
57+
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.5",
58+
"com.github.scopt" %% "scopt" % "3.7.0"
5459
)
5560
}
5661

57-
val verifyDeps = Seq(
58-
"org.scala-lang" % "scala-library" sha1 "4861b00d921952f2dc9a024198bc72590fd7dc5e",
59-
"com.typesafe.akka" % "akka-actor" sha1 "ba05c9b5fb9ab1b9a7f2a14b94c71454d9ade820",
60-
"com.typesafe" % "ssl-config-core" sha1 "7497c001276c3fd76df8204f4611baaa24c5aea9",
61-
"com.typesafe" % "config" sha1 "f533aa6ea13e443b50e639d070986c42d03efc35",
62-
"org.scala-lang.modules" % "scala-java8-compat" sha1 "1e6f1e745bf6d3c34d1e2ab150653306069aaf34",
63-
"com.typesafe.akka" % "akka-agent" sha1 "a902cb66c53d1376a877790265c7dabe672a0cb4",
64-
"org.scala-stm" % "scala-stm" sha1 "1ceeedf00f40697b77a459bdecd451b014960276",
65-
"com.typesafe.akka" % "akka-slf4j" sha1 "7091270169f7d27f5098be591a10cf1fba33c159",
66-
"com.typesafe.akka" % "akka-testkit" sha1 "475ffad312ccee76b79265a459ff02384ac0821c",
67-
"com.typesafe.akka" % "akka-http" sha1 "3141508ce76b029bfb437bb275f73c6f63554704",
68-
"com.typesafe.akka" % "akka-http-core" sha1 "3e312e31aaa8b012b582ebf12f751ada8402248f",
69-
"com.typesafe.akka" % "akka-parsing" sha1 "db7a5ce5708ff0f6feed6939bd15f98a5413c4e5",
70-
"com.typesafe.akka" % "akka-stream" sha1 "4633154311941f0db62a2418a31f49513a505e43",
71-
"org.reactivestreams" % "reactive-streams" sha1 "14b8c877d98005ba3941c9257cfe09f6ed0e0d74",
72-
"org.scala-lang.modules" % "scala-parser-combinators" sha1 "3c1c5475ece77c41e18dd971f8f818c091e4961c",
73-
"ch.megard" % "akka-http-cors" sha1 "a86580cc415a343fa2e5d9aa8a6c6c7391f09372",
74-
"org.json4s" % "json4s-native" sha1 "5474e881ee64da870254517c2eb334fe466e5259",
75-
"org.json4s" % "json4s-core" sha1 "5390fb1ecb7c501e5d9a29ca3d00968e541e290a",
76-
"org.json4s" % "json4s-ast" sha1 "64dec965224fb6ac5ee742ca795716e7489b6402",
77-
"org.json4s" % "json4s-scalap" sha1 "fb05e4f3830064fb2ce9118b2f936c15f0879341",
78-
"com.thoughtworks.paranamer" % "paranamer" sha1 "619eba74c19ccf1da8ebec97a2d7f8ba05773dd6",
79-
"org.scala-lang.modules" % "scala-xml" sha1 "e22de3366a698a9f744106fb6dda4335838cf6a7",
80-
"de.heikoseeberger" % "akka-http-json4s" sha1 "575ba7e823282bf64ebcb4c04e33d9a6c24b5c31",
81-
"io.suzaku" % "boopickle" sha1 "85281da7833655a0fb7c91274c7a97cbe61b990c",
82-
"org.consensusresearch" % "scrypto" sha1 "20177c8d44689b7d3d398ab1f142daf42b8a978c",
83-
"com.chuusai" % "shapeless" sha1 "27e115ffed7917b456e54891de67173f4a68d5f1",
84-
"org.typelevel" % "macro-compat" sha1 "ed809d26ef4237d7c079ae6cf7ebd0dfa7986adf",
85-
"com.google.guava" % "guava" sha1 "3564ef3803de51fb0530a8377ec6100b33b0d073",
86-
"org.whispersystems" % "curve25519-java" sha1 "09091eb56d696d0d0d70d00b84e6037dcd3d98b6",
87-
"com.madgag.spongycastle" % "core" sha1 "9622d6de1407dd3506254fb9b0292eb1206f6991",
88-
"org.iq80.leveldb" % "leveldb" sha1 "e9b071b63a7b40f7d01ae01e99259a2de72426f6",
89-
"org.iq80.leveldb" % "leveldb-api" sha1 "d71173b159a38acd8036d9694f1243afe6be9108",
90-
"org.scorexfoundation" % "iodb" sha1 "0d4b86fe17008bfc5ec0fe4317d6d9c39a81dc85",
91-
"net.jpountz.lz4" % "lz4" sha1 "c708bb2590c0652a642236ef45d9f99ff842a2ce",
92-
"org.slf4j" % "slf4j-api" sha1 "432be7c915d6389efd927e32937a30f7d5556f3e",
93-
"ch.qos.logback" % "logback-classic" sha1 "978cd9fbb43b7abed6379d7b02de052d216e30fc",
94-
"ch.qos.logback" % "logback-core" sha1 "e05d0cb67220937c32d7b4e5a47f967605376f63",
95-
"org.jline" % "jline" sha1 "dfb4e9e15e981634155ce063fa697b2b8964d507",
96-
"io.circe" % "circe-core" sha1 "a2f4e27c41844fac377a7c26f50fe4b6f667c855",
97-
"io.circe" % "circe-numbers" sha1 "8e97dd54d3bca34c730f19b28bce23f4a052302a",
98-
"org.typelevel" % "cats-core" sha1 "267cebe07afbb365b08a6e18be4b137508f16bee",
99-
"org.typelevel" % "cats-macros" sha1 "4733f8227b3a64bbd3be749c682d456b66e4dd6e",
100-
"com.github.mpilquist" % "simulacrum" sha1 "043c9efadda1dc59a5d1a73ce77b145074c7fd35",
101-
"org.typelevel" % "machinist" sha1 "13f7388cf36bcecf51bde7b87a216d5aa101ae2a",
102-
"org.scala-lang" % "scala-reflect" sha1 "23a60e62c5aebe21852ed40443e5b582dabc4d1a",
103-
"org.typelevel" % "cats-kernel" sha1 "24eae5d3c4b0c532b107efe36519324c0c8f03c0",
104-
"io.circe" % "circe-generic" sha1 "38a949ac611a8d48c80fd8c0736d55688d08e69e",
105-
"io.circe" % "circe-parser" sha1 "009d8fce67711164d8f17f0b05fce4d0daa44736",
106-
"io.circe" % "circe-jawn" sha1 "23890a0fa474c84ca5b39312425c0b9879467cd5",
107-
"io.circe" % "circe-generic-extras" sha1 "f9b74914b6fd7193b221bb0eed8d1a82f7fa2aef",
108-
"org.spire-math" % "jawn-parser" sha1 "452b1bdf2982219e1b7c9d27ec316241144b0910",
109-
"commons-io" % "commons-io" sha1 "2852e6e05fbb95076fc091f6d1780f1f8fe35e0f",
110-
"com.trueaccord.scalapb" % "scalapb-runtime" sha1 "efc8fc4d491cd988d75c86787187bd1556086043",
111-
"com.trueaccord.lenses" % "lenses" sha1 "d97d2958814bcfe2f19e1ed2f0f03fd9da5a3961",
112-
"com.lihaoyi" % "fastparse" sha1 "aaf2048f9c6223220eac28c9b6a442f27ba83c55",
113-
"com.lihaoyi" % "fastparse-utils" sha1 "92da792e8608653317ed6eb456f935fbfb2316bc",
114-
"com.lihaoyi" % "sourcecode" sha1 "ef9a771975cb0860f2b42778c5cf1f5d76818979",
115-
"com.google.protobuf" % "protobuf-java" sha1 "b32aba0cbe737a4ca953f71688725972e3ee927c",
116-
"org.scala-sbt.ipcsocket" % "ipcsocket" sha1 "b671d32896b96c0311947309952078bf374a5c17",
117-
"net.java.dev.jna" % "jna" sha1 "55b548d3195efc5280bf1c3f17b49659c54dee40",
118-
"net.java.dev.jna" % "jna-platform" sha1 "00ab163522ed76eb01c8c9a750dedacb134fc8c0",
119-
120-
// Pluggable Consensus (AtomixRaft)
121-
"io.atomix" % "atomix" sha1 "aa30000cb7d864b4ed52b3d0ade62eee425bf490",
122-
"io.atomix" % "atomix-raft" sha1 "e45af08b70220dd010d6f193e3d38147b4be35fe",
123-
"io.netty" % "netty-tcnative-boringssl-static" sha1 "ff5f2d6db5aaa1b4df1b381382cd6581844aad9d",
124-
125-
"io.atomix" % "atomix-primitive" sha1 "73d9bc7c859856832178afd271f1a573e6a7c7e6",
126-
"io.atomix" % "atomix-storage" sha1 "136f0b221acbc2680f099b8ff3a34f8cc1592fe7",
127-
"io.atomix" % "atomix-primary-backup" sha1 "1c895965e3e67a152ffbccb4283b6cee91b4ea61",
128-
"io.atomix" % "atomix-cluster" sha1 "e7bfff8c0466a98cf0bc7b5579983a1b217278f0",
129-
"io.atomix" % "atomix-messaging" sha1 "9a1240a24aa5dc3a35c6057af2a1da3069d47a01",
130-
"io.atomix" % "atomix-utils" sha1 "2cd36ea1749eb7b5836025933ef8954ba686913f",
131-
"io.netty" % "netty-transport" sha1 "4f26f51b86dc1ab19621eb2ac39f1a63682f17f2",
132-
"io.netty" % "netty-buffer" sha1 "65abf40a28ce4f52dd763d0b4f740066a87b5c9e",
133-
"io.netty" % "netty-common" sha1 "b281916c11d3eeec5e839677ec4f2eb9d7586928",
134-
"io.netty" % "netty-resolver" sha1 "07d97be8b3fb195f9d94d9a4afcadef25e08bde2",
135-
"io.netty" % "netty-codec" sha1 "ad4d4309c5b011036ca4df6aca190983d75c6b19",
136-
"io.netty" % "netty-handler" sha1 "9c784510bc6f81177c4f2c2956144438863cdac4",
137-
"io.netty" % "netty-transport-native-epoll" sha1 "58225fd585d628099cff88190dcd4e3589460c01",
138-
"io.netty" % "netty-transport-native-unix-common" sha1 "fee46a4e2b4f2f096532ca443f4f63e08b205318",
139-
"com.google.code.findbugs" % "jsr305" sha1 "40719ea6961c0cb6afaeb6a921eaa1f6afd4cfdf",
140-
"com.google.errorprone" % "error_prone_annotations" sha1 "5f65affce1684999e2f4024983835efc3504012e",
141-
"com.google.j2objc" % "j2objc-annotations" sha1 "ed28ded51a8b1c6b112568def5f4b455e6809019",
142-
"org.codehaus.mojo" % "animal-sniffer-annotations" sha1 "775b7e22fb10026eed3f86e8dc556dfafe35f2d5",
143-
"org.apache.commons" % "commons-lang3" sha1 "6c6c702c89bfff3cd9e80b04d668c5e190d588c6",
144-
"org.apache.commons" % "commons-math3" sha1 "e4ba98f1d4b3c80ec46392f25e094a6a2e58fcbf",
145-
"com.esotericsoftware" % "kryo" sha1 "5053899c213a6ce50a800d4902c5a9de49fe0098",
146-
"com.esotericsoftware" % "reflectasm" sha1 "8b102eed2f12412b254946811111ea48bc03a266",
147-
"org.ow2.asm" % "asm" sha1 "0da08b8cce7bbf903602a25a3a163ae252435795",
148-
"com.esotericsoftware" % "minlog" sha1 "ff07b5f1b01d2f92bb00a337f9a94873712f0827",
149-
"org.objenesis" % "objenesis" sha1 "272bab9a4e5994757044d1fc43ce480c8cb907a4",
150-
"org.hamcrest" % "hamcrest-all" sha1 "63a21ebc981131004ad02e0434e799fd7f3a8d5a"
151-
)
152-
15362
val Integration = config("it") extend Test
15463

15564
val Benchmark = config("benchmark") extend Test
@@ -165,15 +74,16 @@ val root = project.in(file("."))
16574
.settings(commonSettings: _*)
16675
.settings(
16776
libraryDependencies ++= dep,
168-
verifyDependencies in verify ++= verifyDeps,
77+
verifyOutputFile in verifyGenerate := baseDirectory.value / "verify.sbt",
16978
verifyOptions in verify := VerifyOptions(
17079
includeBin = true,
17180
includeScala = true,
17281
includeDependency = true,
17382
excludedJars = Nil,
174-
warnOnUnverifiedFiles = true,
175-
warnOnUnusedVerifications = true
83+
warnOnUnverifiedFiles = false,
84+
warnOnUnusedVerifications = false
17685
),
86+
executableScriptName := name.value,
17787
dist in Universal := ((dist in Universal) dependsOn verify).value
17888
)
17989
.settings(inConfig(Integration)(Defaults.testSettings) : _*)

src/main/resources/mallet.conf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
akka {
2+
# to enable logging use: ["akka.event.slf4j.Slf4jLogger"]
3+
loggers = []
4+
5+
loglevel = OFF
6+
7+
ssl-config {
8+
trustManager = {
9+
stores = [
10+
# TODO: move to Uncyclo maybe?
11+
# When running Mantis with a self signed certificate as described in https://github.com/input-output-hk/mantis/wiki/Configuring-HTTPS-for-JSON-RPC,
12+
# we need to mark the public version of the certificate as trusted for mallet. To do that run:
13+
#
14+
# keytool -export -v \
15+
# -alias mantis \
16+
# -file path/to/mantis.crt \
17+
# -keypass:env PW \
18+
# -storepass:env PW \
19+
# -keystore path/to/mantisCA.jks \
20+
# -rfc
21+
#
22+
# and uncomment the entry below, adjusting the path:
23+
#
24+
# { type = "PEM", path = "path/to/mantis.crt" }
25+
]
26+
}
27+
}
28+
}

src/main/scala/io/iohk/ethereum/App.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.iohk.ethereum
22

33
import io.iohk.ethereum.extvm.VmServerApp
4+
import io.iohk.ethereum.mallet.main.Mallet
45
import io.iohk.ethereum.utils.{Config, Logger}
56

67

@@ -12,13 +13,15 @@ object App extends Logger {
1213
val launchKeytool = "keytool"
1314
val downloadBootstrap = "bootstrap"
1415
val vmServer = "vm-server"
16+
val mallet = "mallet"
1517

1618
args.headOption match {
1719
case None => Mantis.main(args)
1820
case Some(`launchMantis`) => Mantis.main(args.tail)
1921
case Some(`launchKeytool`) => KeyTool.main(args.tail)
2022
case Some(`downloadBootstrap`) => BootstrapDownload.main(args.tail :+ Config.Db.LevelDb.path)
2123
case Some(`vmServer`) => VmServerApp.main(args.tail)
24+
case Some(`mallet`) => Mallet.main(args.tail)
2225
case Some(unknown) =>
2326
log.error(s"Unrecognised launcher option, " +
2427
s"first parameter must be $launchKeytool, $downloadBootstrap, $launchMantis or $vmServer")

src/main/scala/io/iohk/ethereum/consensus/ethash/EthashMiner.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ class EthashMiner(
9090
getBlockForMining(parentBlock) onComplete {
9191
case Success(PendingBlock(block, _)) =>
9292
val headerHash = crypto.kec256(BlockHeader.getEncodedWithoutNonce(block.header))
93-
val startTime = System.currentTimeMillis()
93+
val startTime = System.nanoTime()
9494
val mineResult = mine(headerHash, block.header.difficulty.toLong, dagSize, dag, miningConfig.mineRounds)
95-
val time = System.currentTimeMillis() - startTime
96-
val hashRate = (mineResult.triedHashes * 1000) / time
95+
val time = System.nanoTime() - startTime
96+
//FIXME: consider not reporting hash rate when time delta is zero
97+
val hashRate = if (time > 0) (mineResult.triedHashes.toLong * 1000000000) / time else Long.MaxValue
9798
ethService.submitHashRate(SubmitHashRateRequest(hashRate, ByteString("mantis-miner")))
9899
mineResult match {
99100
case MiningSuccessful(_, pow, nonce) =>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.iohk.ethereum.mallet.common
2+
3+
object Constants {
4+
val AppName = "mallet"
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.iohk.ethereum.mallet.common
2+
3+
sealed trait Err {
4+
def msg: String
5+
}
6+
7+
case class ParserError(msg: String) extends Err
8+
9+
case class RpcClientError(msg: String) extends Err
10+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.iohk.ethereum.mallet.common
2+
3+
import akka.util.ByteString
4+
import org.spongycastle.util.encoders.Hex
5+
6+
object StringUtil {
7+
8+
def unquote(s: String): String = {
9+
require(s.startsWith("\"") && s.endsWith("\"") && s.length > 1, s"[$s] is not quoted")
10+
s.substring(1, s.length - 1)
11+
}
12+
13+
def prefix0x(s: String): String =
14+
if (s.startsWith("0x")) s else "0x" + s
15+
16+
def drop0x(s: String): String =
17+
if (s.startsWith("0x")) s.substring(2) else s
18+
19+
def hexToBytes(s: String): ByteString = {
20+
val digits = drop0x(s)
21+
val padded = if (digits.length % 2 == 0) digits else "0" + digits
22+
ByteString(Hex.decode(padded))
23+
}
24+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.iohk.ethereum.mallet.common
2+
3+
import java.io.{PrintWriter, StringWriter}
4+
import scala.reflect.runtime.universe._
5+
import scala.reflect.runtime.currentMirror
6+
7+
object Util {
8+
9+
/**
10+
* Finds sealed descendant objects of a base class/trait via reflection
11+
* @tparam T base type
12+
* @return a set of objects of type T
13+
*/
14+
def sealedDescendants[T: TypeTag]: Set[T] = {
15+
val symbol = typeOf[T].typeSymbol
16+
val internal = symbol.asInstanceOf[scala.reflect.internal.Symbols#Symbol]
17+
val descendants = internal.sealedDescendants.map(_.asInstanceOf[Symbol]) - symbol
18+
descendants.map { d =>
19+
val module = d.owner.typeSignature.member(d.name.toTermName)
20+
currentMirror.reflectModule(module.asModule).instance.asInstanceOf[T]
21+
}
22+
}
23+
24+
def exceptionToString(ex: Throwable): String = {
25+
val sw = new StringWriter()
26+
sw.append(ex.getMessage + "\n")
27+
ex.printStackTrace(new PrintWriter(sw))
28+
sw.toString
29+
}
30+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.iohk.ethereum.mallet.interpreter
2+
3+
import akka.util.ByteString
4+
import io.iohk.ethereum.mallet.common.StringUtil
5+
6+
/**
7+
* Holds classes that represent constructs and literal types parsed from user input
8+
*/
9+
object AST {
10+
11+
case class Cmd(name: String, args: List[Argument])
12+
13+
case class Argument(name: Option[String], value: Literal)
14+
15+
/**
16+
* Base trait for literal types of arguments from user input.
17+
* Note: these are different and require mapping to command parameter types
18+
*/
19+
sealed trait Literal {
20+
def input: String
21+
}
22+
23+
case class Quoted(input: String) extends Literal {
24+
def unquote: String = StringUtil.unquote(input)
25+
}
26+
27+
case class Dec(input: String) extends Literal {
28+
def number: BigInt = BigInt(input)
29+
}
30+
31+
case class Hex(input: String) extends Literal {
32+
def bytes: ByteString = StringUtil.hexToBytes(input)
33+
def digits: String = StringUtil.drop0x(input)
34+
def number: BigInt = BigInt(digits, 16)
35+
}
36+
37+
case class Identifier(input: String) extends Literal
38+
39+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package io.iohk.ethereum.mallet.interpreter
2+
3+
import io.iohk.ethereum.mallet.common.{Err, ParserError}
4+
import AST._
5+
6+
import scala.util.parsing.combinator.{JavaTokenParsers, RegexParsers}
7+
8+
/**
9+
* EBNF syntax definition:
10+
*
11+
* cmd = identifier, { argument-list };
12+
* argument-list = "(", (empty | argument, { ",", argument }), ")";
13+
* argument = named-argument | literal;
14+
* named-argument = identifier, "=", literal;
15+
* literal = quoted | dec | hex | identifier;
16+
* empty = { whitespace };
17+
* identifier = ? valid identifier ?;
18+
* dec = ? decimal number ?;
19+
* hex = 0x, ? hex digits ?;
20+
* quoted = ? " delimited string ?;
21+
*/
22+
object CmdParser extends RegexParsers with JavaTokenParsers {
23+
24+
val quoted: Parser[Quoted] = """\"([^"]|(?<=\\)")*\"""".r ^^ Quoted.apply
25+
26+
val dec: Parser[Dec] = wholeNumber ^^ Dec.apply
27+
28+
val hex: Parser[Hex] = "0x[A-Fa-f0-9]*".r ^^ Hex.apply
29+
30+
val identifier: Parser[Identifier] = ident ^^ Identifier.apply
31+
32+
val literal: Parser[Literal] = quoted | hex | dec | identifier
33+
34+
val namedArgument: Parser[Argument] = (identifier <~ "=") ~ literal ^^ {
35+
case name ~ v => Argument(Some(name.input), v)
36+
}
37+
38+
val argument: Parser[Argument] = namedArgument | literal ^^ (v => Argument(None, v))
39+
40+
val empty: Parser[List[Nothing]] = """\s*""".r ^^ (_ => Nil)
41+
42+
val argumentList: Parser[List[Argument]] = (argument ~ ("," ~> argument).* ^^ {
43+
case a ~ as => a :: as
44+
}) | empty
45+
46+
47+
val funCall: Parser[Cmd] = ident ~ ("(" ~> argumentList <~ ")").? ^^ {
48+
case name ~ arguments =>
49+
Cmd(name, arguments.getOrElse(Nil))
50+
}
51+
52+
53+
def apply(line: String): Either[Err, Cmd] = parseAll(funCall, line) match {
54+
case NoSuccess(message, _) =>
55+
val msg = if (line.trim.isEmpty) "" else message
56+
Left(ParserError(msg))
57+
58+
case Success(matched, _) =>
59+
Right(matched)
60+
}
61+
}

0 commit comments

Comments
 (0)