Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
95ac2d4
commit 235fb7b
Showing
22 changed files
with
360 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 113 additions & 1 deletion
114
src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,115 @@ | ||
package io.iohk.ethereum.faucet.jsonrpc class FaucetBuilder { | ||
package io.iohk.ethereum.faucet.jsonrpc | ||
|
||
import java.security.SecureRandom | ||
|
||
import akka.actor.ActorSystem | ||
import io.iohk.ethereum.faucet.FaucetConfigBuilder | ||
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcControllerCommon.JsonRpcConfig | ||
import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer | ||
import io.iohk.ethereum.keystore.KeyStoreImpl | ||
import io.iohk.ethereum.mallet.service.RpcClient | ||
import io.iohk.ethereum.nodebuilder.SecureRandomBuilder | ||
import io.iohk.ethereum.utils.{KeyStoreConfig, Logger} | ||
|
||
import scala.concurrent.Future | ||
|
||
|
||
trait ActorSystemBuilder { | ||
def systemName: String | ||
implicit lazy val system: ActorSystem = ActorSystem(systemName) | ||
} | ||
|
||
trait FaucetControllerBuilder { | ||
self: FaucetConfigBuilder with ActorSystemBuilder => | ||
|
||
implicit val ec = system.dispatcher | ||
|
||
/*private val walletRpcClient = | ||
new WalletRpcClient(faucetConfig.walletRpcAddress, sslContext.toOption) | ||
private val faucetService: FaucetService = new FaucetServiceImpl(walletRpcClient) | ||
*/ | ||
|
||
} | ||
|
||
trait FaucetRpcServiceBuilder { | ||
self: FaucetConfigBuilder with FaucetControllerBuilder with ActorSystemBuilder => | ||
|
||
val keyStore = new KeyStoreImpl(KeyStoreConfig.customKeyStoreConfig(faucetConfig.keyStoreDir), new SecureRandom()) | ||
val rpcClient = new RpcClient(faucetConfig.rpcAddress) | ||
val faucetRpcService = new FaucetRpcService(rpcClient, keyStore, faucetConfig) | ||
} | ||
|
||
trait FaucetJsonRpcHealthCheckBuilder { | ||
self: FaucetRpcServiceBuilder => | ||
|
||
val faucetJsonRpcHealthCheck = new FaucetJsonRpcHealthCheck(faucetRpcService) | ||
} | ||
|
||
trait JsonRpcConfigBuilder { self: FaucetConfigBuilder => | ||
|
||
object Apis { | ||
val Rpc = "rpc" | ||
|
||
val available = Seq(Rpc) | ||
} | ||
|
||
val availableApis: List[String] = Apis.available.toList //TODO: mmmmm | ||
lazy val jsonRpcConfig: JsonRpcConfig = JsonRpcConfig(rawMantisConfig, Apis.available.toList) | ||
} | ||
|
||
trait FaucetJsonRpcControllerBuilder { | ||
self: JsonRpcConfigBuilder with FaucetRpcServiceBuilder => | ||
|
||
val faucetJsonRpcController = new FaucetJsonRpcController( | ||
new FaucetJRC(faucetRpcService, jsonRpcConfig).handleFaucetRequest, | ||
jsonRpcConfig | ||
) | ||
} | ||
|
||
trait FaucetJsonRpcHttpServerBuilder { | ||
self: ActorSystemBuilder | ||
with JsonRpcConfigBuilder | ||
with SecureRandomBuilder | ||
with FaucetJsonRpcHealthCheckBuilder | ||
with FaucetJsonRpcControllerBuilder => | ||
|
||
val faucetJsonRpcHttpServer = JsonRpcHttpServer( | ||
faucetJsonRpcController, | ||
faucetJsonRpcHealthCheck, | ||
jsonRpcConfig.httpServerConfig, | ||
secureRandom, | ||
// DispatcherId("midnight.async.dispatchers.json-rpc-http"), //TODO: add dispatcher | ||
//() => sslContext | ||
) | ||
} | ||
|
||
class FaucetServer extends | ||
ActorSystemBuilder | ||
with FaucetConfigBuilder | ||
with JsonRpcConfigBuilder | ||
with SecureRandomBuilder | ||
with FaucetControllerBuilder | ||
with FaucetRpcServiceBuilder | ||
with FaucetJsonRpcHealthCheckBuilder | ||
with FaucetJsonRpcControllerBuilder | ||
with FaucetJsonRpcHttpServerBuilder | ||
with Logger { | ||
|
||
override def systemName: String = "Faucet-system" | ||
|
||
def start(): Unit = { | ||
log.info("About to start Faucet server") | ||
|
||
log.info("About to start Faucet JSON-RPC server") | ||
startJsonRpcHttpServer() | ||
} | ||
|
||
//TODO: load if jsonRpcConfig.httpServerConfig.enabled | ||
private[this] def startJsonRpcHttpServer() = | ||
faucetJsonRpcHttpServer match { | ||
case Right(jsonRpcServer) => jsonRpcServer.run() | ||
case Left(error) => | ||
Future.failed(new RuntimeException(s"$error")) | ||
} | ||
} |
33 changes: 29 additions & 4 deletions
33
src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetDomain.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,37 @@ | ||
package io.iohk.ethereum.faucet.jsonrpc | ||
|
||
import akka.util.ByteString | ||
import io.iohk.ethereum.domain.Address | ||
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcControllerCommon.JsonDecoder.NoParamsDecoder | ||
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcControllerCommon.{JsonDecoder, JsonEncoder} | ||
import io.iohk.ethereum.jsonrpc.JsonMethodsImplicits | ||
import io.iohk.ethereum.jsonrpc.JsonRpcErrors.InvalidParams | ||
import org.json4s.JsonAST.{JArray, JObject, JString} | ||
|
||
object FucetDomain { | ||
object FaucetDomain { | ||
|
||
case class SendFundsRequest(address: String) | ||
case class SendFundsResponse(jobHash: ByteString) | ||
case class SendFundsRequest(address: Address) | ||
object SendFundsRequest extends JsonMethodsImplicits { | ||
implicit val sendFundsRequestDecoder: JsonDecoder[SendFundsRequest] = { | ||
case Some(JArray((input: JString) :: Nil)) => extractAddress(input).map(SendFundsRequest(_)) | ||
case _ => Left(InvalidParams()) | ||
} | ||
} | ||
|
||
case class SendFundsResponse(txId: ByteString) | ||
object SendFundsResponse extends JsonMethodsImplicits { | ||
implicit val sendFundsResponseEncoder: JsonEncoder[SendFundsResponse] = (t: SendFundsResponse) => encodeAsHex(t.txId) | ||
} | ||
|
||
case class StatusRequest() | ||
case class StatusResponse(status: FaucetStatus) | ||
object StatusRequest extends JsonMethodsImplicits { | ||
implicit val statusRequestDecoder: JsonDecoder[StatusRequest] = new NoParamsDecoder(StatusRequest()) | ||
} | ||
|
||
case class StatusResponse(status: String) | ||
object StatusResponse extends JsonMethodsImplicits { | ||
implicit val statusEncoder: JsonEncoder[StatusResponse] = (t: StatusResponse) => JObject( | ||
"status" -> JString(t.status) | ||
) | ||
} | ||
} |
35 changes: 34 additions & 1 deletion
35
src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetJRC.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,36 @@ | ||
package io.iohk.ethereum.faucet.jsonrpc class FaucetJRC { | ||
package io.iohk.ethereum.faucet.jsonrpc | ||
|
||
import io.iohk.ethereum.faucet.jsonrpc.FaucetDomain._ | ||
import io.iohk.ethereum.jsonrpc.JsonRpcController.Apis | ||
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcControllerCommon.JsonRpcConfig | ||
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcControllerCommon | ||
import io.iohk.ethereum.jsonrpc.{JsonRpcRequest, JsonRpcResponse} | ||
|
||
import scala.concurrent.Future | ||
|
||
class FaucetJRC( | ||
faucetRpcService: FaucetRpcService, | ||
override val config: JsonRpcConfig | ||
) extends JsonRpcControllerCommon { | ||
|
||
override def enabledApis: Seq[String] = config.apis :+ Apis.Rpc | ||
|
||
override def handleFn: Map[String, PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]]] = Map( | ||
Apis.Eth -> handleFaucetRequest, | ||
) | ||
|
||
def handleFaucetRequest: PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]] = { | ||
case req @ JsonRpcRequest(_, FaucetJRC.SendFunds, _, _) => | ||
handle[SendFundsRequest, SendFundsResponse](faucetRpcService.sendFunds, req) | ||
case req @ JsonRpcRequest(_, FaucetJRC.Status, _, _) => | ||
handle[StatusRequest, StatusResponse](faucetRpcService.status, req) | ||
} | ||
} | ||
|
||
object FaucetJRC { | ||
private val Prefix = "faucet_" | ||
|
||
val SendFunds: String = Prefix + "sendFunds" | ||
val Status: String = Prefix + "status" | ||
} | ||
|
14 changes: 11 additions & 3 deletions
14
src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetJsonRpcController.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 4 additions & 2 deletions
6
src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetJsonRpcHealthCheck.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 66 additions & 1 deletion
67
src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,70 @@ | ||
package io.iohk.ethereum.faucet.jsonrpc | ||
|
||
class FaucetRpcService { | ||
import java.time.Clock | ||
|
||
import akka.http.scaladsl.model.RemoteAddress | ||
import akka.util.ByteString | ||
import com.twitter.util.LruMap | ||
import io.iohk.ethereum.domain.{Address, Transaction} | ||
import io.iohk.ethereum.faucet.FaucetConfig | ||
import io.iohk.ethereum.faucet.jsonrpc.FaucetDomain.{SendFundsRequest, SendFundsResponse, StatusRequest, StatusResponse} | ||
import io.iohk.ethereum.jsonrpc.ServiceResponse | ||
import io.iohk.ethereum.keystore.KeyStore | ||
import io.iohk.ethereum.mallet.service.RpcClient | ||
import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc | ||
import io.iohk.ethereum.rlp | ||
import io.iohk.ethereum.utils.{ByteStringUtils, Logger} | ||
|
||
import scala.concurrent.Future | ||
|
||
class FaucetRpcService(rpcClient: RpcClient, keyStore: KeyStore, config: FaucetConfig, clock: Clock = Clock.systemUTC()) | ||
extends Logger { | ||
|
||
private val latestRequestTimestamps = new LruMap[RemoteAddress, Long](config.latestTimestampCacheSize) | ||
|
||
private val wallet = keyStore.unlockAccount(config.walletAddress, config.walletPassword) match { | ||
case Right(w) => w | ||
case Left(err) => | ||
throw new RuntimeException(s"Cannot unlock wallet for use in faucet (${config.walletAddress}), because of $err") | ||
} | ||
|
||
def sendFunds(sendFundsRequest: SendFundsRequest): ServiceResponse[SendFundsResponse] = { | ||
val clientAddr: RemoteAddress = ??? | ||
val targetAddress: String = ??? | ||
val timeMillis = clock.instant().toEpochMilli | ||
val latestRequestTimestamp = latestRequestTimestamps.getOrElse(clientAddr, 0L) | ||
if (latestRequestTimestamp + config.minRequestInterval.toMillis < timeMillis) { | ||
latestRequestTimestamps.put(clientAddr, timeMillis) | ||
|
||
val res = for { | ||
nonce <- rpcClient.getNonce(wallet.address) | ||
txId <- rpcClient.sendTransaction(prepareTx(Address(targetAddress), nonce)) | ||
} yield txId | ||
|
||
res match { | ||
case Right(txId) => | ||
val txIdHex = s"0x${ByteStringUtils.hash2string(txId)}" | ||
log.info(s"Sending ${config.txValue} ETH to $targetAddress in tx: $txIdHex. Requested by $clientAddr") | ||
//complete(StatusCodes.OK, txIdHex) | ||
Future.successful(Right(SendFundsResponse(txId))) //TODO: change... | ||
|
||
case Left(err) => | ||
log.error(s"An error occurred while using faucet: $err") | ||
Future.successful(???) | ||
//complete(StatusCodes.InternalServerError) | ||
} | ||
} else Future.successful(???)//complete(StatusCodes.TooManyRequests) | ||
} | ||
|
||
private def prepareTx(targetAddress: Address, nonce: BigInt): ByteString = { | ||
val transaction = | ||
Transaction(nonce, config.txGasPrice, config.txGasLimit, Some(targetAddress), config.txValue, ByteString()) | ||
|
||
val stx = wallet.signTx(transaction, None) | ||
ByteString(rlp.encode(stx.tx.toRLPEncodable)) | ||
} | ||
|
||
def status(statusRequest: StatusRequest): ServiceResponse[StatusResponse] = { | ||
Future.successful(Right(StatusResponse("ok"))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
src/main/scala/io/iohk/ethereum/jsonrpc/DebugJsonMethodsImplicits.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.