Skip to content

Commit 8f4961a

Browse files
author
Łukasz Gąsior
authored
Merge pull request #426 from input-output-hk/feature/testmode
Add testmode
2 parents 35e0661 + fe62c56 commit 8f4961a

Some content is hidden

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

49 files changed

+1233
-304
lines changed

build.sbt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ val dep = {
4545
"com.miguno.akka" %% "akka-mock-scheduler" % "0.5.1" % "it,test",
4646
"commons-io" % "commons-io" % "2.5",
4747
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
48+
"org.scala-sbt.ipcsocket" % "ipcsocket" % "1.0.0",
4849

4950
// Pluggable Consensus: AtomixRaft
5051
"io.atomix" % "atomix" % "2.1.0-beta1",
@@ -112,6 +113,9 @@ val verifyDeps = Seq(
112113
"com.lihaoyi" % "fastparse-utils" sha1 "92da792e8608653317ed6eb456f935fbfb2316bc",
113114
"com.lihaoyi" % "sourcecode" sha1 "ef9a771975cb0860f2b42778c5cf1f5d76818979",
114115
"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",
115119

116120
// Pluggable Consensus (AtomixRaft)
117121
"io.atomix" % "atomix" sha1 "aa30000cb7d864b4ed52b3d0ade62eee425bf490",

src/ets/scala/io/iohk/ethereum/ets/blockchain/ScenarioSetup.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ abstract class ScenarioSetup(_vm: VMImpl, scenario: BlockchainScenario) {
4646

4747
val consensus: TestConsensus = ScenarioSetup.loadEthashConsensus(_vm, blockchain, blockchainConfig)
4848

49-
val emptyWorld = blockchain.getWorldStateProxy(-1, UInt256.Zero, None)
49+
val emptyWorld = blockchain.getWorldStateProxy(-1, UInt256.Zero, None, false, true)
5050

5151
val ledger = new LedgerImpl(blockchain, new BlockQueue(blockchain, 10, 10), blockchainConfig, consensus)
5252

src/it/scala/io/iohk/ethereum/SimulateTransactionTest/SimulateTransactionTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ trait ScenarioSetup extends EphemBlockchainTestSetup {
122122

123123
override lazy val ledger: LedgerImpl = newLedger()
124124

125-
val emptyWorld = blockchain.getWorldStateProxy(-1, UInt256.Zero, None)
125+
val emptyWorld = blockchain.getWorldStateProxy(-1, UInt256.Zero, None, false, true)
126126

127127
val existingAddress = Address(10)
128128
val existingAccount = Account(nonce = UInt256.Zero, balance = UInt256(10))

src/main/resources/application.conf

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ mantis {
1717
# timeout for shutting down the ActorSystem
1818
shutdown-timeout = "15.seconds"
1919

20+
# Whether to run Mantis in test mode (similar to --test flag in cpp-ethereum).
21+
# When set, test validators and consensus are used by this node.
22+
# It also enables test_ RPC endpoints.
23+
testmode = false
24+
2025
# one of the algorithms defined here:
2126
# https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom
2227
# Uncomment this to specify, otherwise use the default implementation
@@ -144,50 +149,60 @@ mantis {
144149
}
145150

146151
rpc {
147-
# JSON-RPC mode
148-
# Available modes are: http, https
149-
# Choosing https requires creating a certificate and setting up 'certificate-keystore-path' and
150-
# 'certificate-password-file'
151-
# See: https://github.com/input-output-hk/mantis/wiki/Creating-self-signed-certificate-for-using-JSON-RPC-with-HTTPS
152-
mode = "http"
153-
154-
# Whether to enable JSON-RPC endpoint
155-
enabled = true
156-
157-
# Listening address of JSON-RPC HTTP/HTTPS endpoint
158-
interface = "localhost"
159-
160-
# Listening port of JSON-RPC HTTP/HTTPS endpoint
161-
port = 8546
162-
163-
# Path to the keystore storing the certificates (used only for https)
164-
# null value indicates HTTPS is not being used
165-
certificate-keystore-path = null
152+
http {
153+
# JSON-RPC mode
154+
# Available modes are: http, https
155+
# Choosing https requires creating a certificate and setting up 'certificate-keystore-path' and
156+
# 'certificate-password-file'
157+
# See: https://github.com/input-output-hk/mantis/wiki/Creating-self-signed-certificate-for-using-JSON-RPC-with-HTTPS
158+
mode = "http"
159+
160+
# Whether to enable JSON-RPC HTTP(S) endpoint
161+
enabled = true
162+
163+
# Listening address of JSON-RPC HTTP(S) endpoint
164+
interface = "localhost"
165+
166+
# Listening port of JSON-RPC HTTP(S) endpoint
167+
port = 8546
168+
169+
# Path to the keystore storing the certificates (used only for https)
170+
# null value indicates HTTPS is not being used
171+
certificate-keystore-path = null
172+
173+
# Type of certificate keystore being used
174+
# null value indicates HTTPS is not being used
175+
certificate-keystore-type = null
176+
177+
# File with the password used for accessing the certificate keystore (used only for https)
178+
# null value indicates HTTPS is not being used
179+
certificate-password-file = null
180+
181+
# Domains allowed to query RPC endpoint. Use "*" to enable requests from
182+
# any domain.
183+
cors-allowed-origins = []
184+
}
166185

167-
# Type of certificate keystore being used
168-
# null value indicates HTTPS is not being used
169-
certificate-keystore-type = null
186+
ipc {
187+
# Whether to enable JSON-RPC over IPC
188+
enabled = true
170189

171-
# File with the password used for accessing the certificate keystore (used only for https)
172-
# null value indicates HTTPS is not being used
173-
certificate-password-file = null
190+
# Path to IPC socket file
191+
socket-file = ${mantis.datadir}"/mantis.ipc"
192+
}
174193

175194
# Enabled JSON-RPC APIs over the JSON-RPC endpoint
176-
# Available choices are: eth, web3, net, personal, daedalus
195+
# Available choices are: eth, web3, net, personal, test, daedalus, iele
177196
apis = "eth,web3,net,personal,daedalus"
178197

179-
# Domains allowed to query RPC endpoint. Use "*" to enable requests from
180-
# any domain.
181-
cors-allowed-origins = []
182-
183198
# Maximum number of blocks for daedalus_getAccountTransactions
184199
account-transactions-max-blocks = 50000
185200

186201
net {
187202
peer-manager-timeout = 5.seconds
188203
}
189204

190-
active-timeout = 5.seconds
205+
miner-active-timeout = 5.seconds
191206
}
192207
}
193208

@@ -542,4 +557,3 @@ akka {
542557
logger-startup-timeout = 30s
543558
log-dead-letters = off
544559
}
545-
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package io.iohk.ethereum
22

3-
import io.iohk.ethereum.nodebuilder.StdNode
3+
import io.iohk.ethereum.nodebuilder.{StdNode, TestNode}
4+
import io.iohk.ethereum.utils.Config
45

56
object Mantis {
67
def main(args: Array[String]): Unit = {
7-
val node = new StdNode
8+
val node =
9+
if (Config.testmode) new TestNode
10+
else new StdNode
11+
812
node.start()
913
}
1014
}

src/main/scala/io/iohk/ethereum/blockchain/data/GenesisDataLoader.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class GenesisDataLoader(
8686
} yield ()
8787
}
8888

89-
private def loadGenesisData(genesisData: GenesisData): Try[Unit] = {
89+
def loadGenesisData(genesisData: GenesisData): Try[Unit] = {
9090
import MerklePatriciaTrie.defaultByteArraySerializable
9191

9292
val ephemDataSource = EphemDataSource()

src/main/scala/io/iohk/ethereum/consensus/ConsensusBuilder.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import io.iohk.ethereum.consensus.ethash.EthashConsensus
55
import io.iohk.ethereum.nodebuilder._
66
import io.iohk.ethereum.utils.{Config, Logger}
77

8+
trait ConsensusBuilder {
9+
def consensus: Consensus
10+
}
11+
812
/**
913
* A consensus builder is responsible to instantiate the consensus protocol.
1014
* This is done dynamically when Mantis boots, based on its configuration.
@@ -13,7 +17,7 @@ import io.iohk.ethereum.utils.{Config, Logger}
1317
* [[io.iohk.ethereum.consensus.ethash.EthashConsensus EthashConsensus]],
1418
* [[io.iohk.ethereum.consensus.atomixraft.AtomixRaftConsensus AtomixRaftConsensus]]
1519
*/
16-
trait ConsensusBuilder {
20+
trait StdConsensusBuilder extends ConsensusBuilder {
1721
self: VmBuilder with BlockchainBuilder with BlockchainConfigBuilder with ConsensusConfigBuilder with Logger
1822

1923
private lazy val mantisConfig = Config.config

src/main/scala/io/iohk/ethereum/consensus/TestConsensusBuilder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import io.iohk.ethereum.utils.Logger
77
* A [[io.iohk.ethereum.consensus.ConsensusBuilder ConsensusBuilder]] that builds a
88
* [[io.iohk.ethereum.consensus.TestConsensus TestConsensus]]
99
*/
10-
trait TestConsensusBuilder { self: ConsensusBuilder
10+
trait TestConsensusBuilder { self: StdConsensusBuilder
1111
protected def buildTestConsensus(): TestConsensus =
1212
buildConsensus().asInstanceOf[TestConsensus] // we are in tests, so if we get an exception, so be it
1313
}
1414

1515
/** A standard [[TestConsensusBuilder]] cake. */
16-
trait StdTestConsensusBuilder extends ConsensusBuilder
16+
trait StdTestConsensusBuilder extends StdConsensusBuilder
1717
with TestConsensusBuilder
1818
with VmBuilder
1919
with VmConfigBuilder

src/main/scala/io/iohk/ethereum/domain/Blockchain.scala

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,15 @@ trait Blockchain {
181181

182182
def getWorldStateProxy(blockNumber: BigInt,
183183
accountStartNonce: UInt256,
184-
stateRootHash: Option[ByteString] = None,
185-
noEmptyAccounts: Boolean = false,
186-
ethCompatibleStorage: Boolean = true): WS
184+
stateRootHash: Option[ByteString],
185+
noEmptyAccounts: Boolean,
186+
ethCompatibleStorage: Boolean): WS
187187

188188
def getReadOnlyWorldStateProxy(blockNumber: Option[BigInt],
189189
accountStartNonce: UInt256,
190-
stateRootHash: Option[ByteString] = None,
191-
noEmptyAccounts: Boolean = false,
192-
ethCompatibleStorage: Boolean = true): WS
190+
stateRootHash: Option[ByteString],
191+
noEmptyAccounts: Boolean,
192+
ethCompatibleStorage: Boolean): WS
193193

194194
def pruneState(blockNumber: BigInt): Unit
195195

@@ -316,24 +316,24 @@ class BlockchainImpl(
316316
override def getWorldStateProxy(blockNumber: BigInt,
317317
accountStartNonce: UInt256,
318318
stateRootHash: Option[ByteString],
319-
noEmptyAccount: Boolean = false,
320-
ethCompatibleStorage: Boolean = true): InMemoryWorldStateProxy =
319+
noEmptyAccounts: Boolean,
320+
ethCompatibleStorage: Boolean): InMemoryWorldStateProxy =
321321
InMemoryWorldStateProxy(
322322
evmCodeStorage,
323323
nodesKeyValueStorageFor(Some(blockNumber)),
324324
accountStartNonce,
325325
(number: BigInt) => getBlockHeaderByNumber(number).map(_.hash),
326326
stateRootHash,
327-
noEmptyAccount,
327+
noEmptyAccounts,
328328
ethCompatibleStorage
329329
)
330330

331331
//FIXME Maybe we can use this one in regular execution too and persist underlying storage when block execution is successful
332332
override def getReadOnlyWorldStateProxy(blockNumber: Option[BigInt],
333333
accountStartNonce: UInt256,
334334
stateRootHash: Option[ByteString],
335-
noEmptyAccount: Boolean = false,
336-
ethCompatibleStorage: Boolean = true): InMemoryWorldStateProxy =
335+
noEmptyAccounts: Boolean,
336+
ethCompatibleStorage: Boolean): InMemoryWorldStateProxy =
337337
InMemoryWorldStateProxy(
338338
evmCodeStorage,
339339
ReadOnlyNodeStorage(nodesKeyValueStorageFor(blockNumber)),

src/main/scala/io/iohk/ethereum/extvm/ExtVMInterface.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import akka.stream.{ActorMaterializer, OverflowStrategy}
77
import akka.stream.scaladsl.{Framing, Keep, Sink, SinkQueueWithCancel, Source, SourceQueueWithComplete, Tcp}
88
import akka.util.ByteString
99
import io.iohk.ethereum.ledger.{InMemoryWorldStateProxy, InMemoryWorldStateProxyStorage}
10-
import io.iohk.ethereum.utils.BlockchainConfig
10+
import io.iohk.ethereum.utils.{BlockchainConfig, VmConfig}
1111
import io.iohk.ethereum.vm._
1212

1313
import scala.annotation.tailrec
1414
import scala.util.{Failure, Success, Try}
1515

16-
class ExtVMInterface(host: String, port: Int, blockchainConfig: BlockchainConfig, testMode: Boolean)(implicit system: ActorSystem)
16+
class ExtVMInterface(externaVmConfig: VmConfig.ExternalConfig, blockchainConfig: BlockchainConfig, testMode: Boolean)(implicit system: ActorSystem)
1717
extends VM[InMemoryWorldStateProxy, InMemoryWorldStateProxyStorage]{
1818

1919
private implicit val materializer = ActorMaterializer()
@@ -29,7 +29,7 @@ class ExtVMInterface(host: String, port: Int, blockchainConfig: BlockchainConfig
2929
private def initConnection(): Unit = {
3030
close()
3131

32-
val connection = Tcp().outgoingConnection(host, port)
32+
val connection = Tcp().outgoingConnection(externaVmConfig.host, externaVmConfig.port)
3333

3434
val (connOut, connIn) = Source.queue[ByteString](QueueBufferSize, OverflowStrategy.dropTail)
3535
.via(connection)
@@ -41,7 +41,7 @@ class ExtVMInterface(host: String, port: Int, blockchainConfig: BlockchainConfig
4141
out = Some(connOut)
4242
in = Some(connIn)
4343

44-
val client = new VMClient(new MessageHandler(connIn, connOut), testMode)
44+
val client = new VMClient(externaVmConfig, new MessageHandler(connIn, connOut), testMode)
4545
client.sendHello(ApiVersionProvider.version, blockchainConfig)
4646
//TODO: await hello response, check version
4747

src/main/scala/io/iohk/ethereum/extvm/VMClient.scala

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import io.iohk.ethereum.vm.{WorldStateProxy, _}
55
import Implicits._
66
import akka.util.ByteString
77
import io.iohk.ethereum.domain._
8-
import io.iohk.ethereum.utils.{BlockchainConfig, Logger}
8+
import io.iohk.ethereum.utils.{BlockchainConfig, Logger, VmConfig}
99

1010
import scala.annotation.tailrec
1111

@@ -14,13 +14,17 @@ import scala.annotation.tailrec
1414
* This is useful to override configuration for each test, rather than to recreate the VM.
1515
*/
1616
class VMClient(
17+
externalVmConfig: VmConfig.ExternalConfig,
1718
messageHandler: MessageHandler,
1819
testMode: Boolean)
1920
extends Logger {
2021

2122
def sendHello(version: String, blockchainConfig: BlockchainConfig): Unit = {
2223
val config = BlockchainConfigForEvm(blockchainConfig)
23-
val configMsg = msg.Hello.Config.EthereumConfig(buildEthereumConfigMsg(BlockchainConfigForEvm(blockchainConfig)))
24+
val configMsg = externalVmConfig.vmType match {
25+
case VmConfig.ExternalConfig.VmTypeIele => msg.Hello.Config.IeleConfig(buildIeleConfigMsg())
26+
case _ => msg.Hello.Config.EthereumConfig(buildEthereumConfigMsg(config))
27+
}
2428
val helloMsg = msg.Hello(version, configMsg)
2529
messageHandler.sendMessage(helloMsg)
2630
}
@@ -125,11 +129,12 @@ class VMClient(
125129
import msg.CallContext.Config
126130
val blockHeader = buildBlockHeaderMsg(ctx.blockHeader)
127131

128-
val ethereumConfig =
129-
if (testMode)
130-
Config.EthereumConfig(buildEthereumConfigMsg(ctx.evmConfig.blockchainConfig))
131-
else
132-
Config.Empty
132+
val config = externalVmConfig.vmType match {
133+
case VmConfig.ExternalConfig.VmTypeIele => Config.IeleConfig(buildIeleConfigMsg()) // always pass config for IELE
134+
case VmConfig.ExternalConfig.VmTypeKevm => Config.EthereumConfig(buildEthereumConfigMsg(ctx.evmConfig.blockchainConfig)) // always pass config for KEVM
135+
case _ if testMode => Config.EthereumConfig(buildEthereumConfigMsg(ctx.evmConfig.blockchainConfig))
136+
case _ => Config.Empty
137+
}
133138

134139
msg.CallContext(
135140
callerAddr = ctx.callerAddr,
@@ -139,7 +144,7 @@ class VMClient(
139144
gasPrice = ctx.gasPrice,
140145
gasProvided = ctx.startGas,
141146
blockHeader = Some(blockHeader),
142-
config = ethereumConfig
147+
config = config
143148
)
144149
}
145150

@@ -154,6 +159,9 @@ class VMClient(
154159
accountStartNonce = blockchainConfig.accountStartNonce
155160
)
156161

162+
private def buildIeleConfigMsg(): msg.IeleConfig =
163+
msg.IeleConfig()
164+
157165
private def buildBlockHeaderMsg(header: BlockHeader): msg.BlockHeader =
158166
msg.BlockHeader(
159167
beneficiary = header.beneficiary,

src/main/scala/io/iohk/ethereum/jsonrpc/EthJsonMethodsImplicits.scala

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -565,12 +565,6 @@ object EthJsonMethodsImplicits extends JsonMethodsImplicits {
565565
data = data.getOrElse(ByteString("")))
566566
}
567567

568-
private def optionalQuantity(input: JValue): Either[JsonRpcError, Option[BigInt]] =
569-
input match {
570-
case JNothing => Right(None)
571-
case o => extractQuantity(o).map(Some(_))
572-
}
573-
574568
implicit val daedalus_getAccountTransactions =
575569
new JsonDecoder[GetAccountTransactionsRequest] with JsonEncoder[GetAccountTransactionsResponse] {
576570
def decodeJson(params: Option[JArray]): Either[JsonRpcError, GetAccountTransactionsRequest] =
@@ -587,4 +581,19 @@ object EthJsonMethodsImplicits extends JsonMethodsImplicits {
587581
override def encodeJson(t: GetAccountTransactionsResponse): JValue =
588582
JObject("transactions" -> JArray(t.transactions.map(Extraction.decompose).toList))
589583
}
584+
585+
implicit val eth_getStorageRoot = new JsonDecoder[GetStorageRootRequest] with JsonEncoder[GetStorageRootResponse] {
586+
def decodeJson(params: Option[JArray]): Either[JsonRpcError, GetStorageRootRequest] =
587+
params match {
588+
case Some(JArray((addressStr: JString) :: (blockValue: JValue) :: Nil)) =>
589+
for {
590+
address <- extractAddress(addressStr)
591+
block <- extractBlockParam(blockValue)
592+
} yield GetStorageRootRequest(address, block)
593+
case _ => Left(InvalidParams())
594+
}
595+
596+
def encodeJson(t: GetStorageRootResponse): JValue = encodeAsHex(t.storageRoot)
597+
}
598+
590599
}

0 commit comments

Comments
 (0)