feat: added mining routes

This commit is contained in:
darwincereska
2025-12-18 09:40:05 -05:00
parent 3c097af03d
commit 89e45128b6

View File

@@ -0,0 +1,229 @@
package org.ccoin.routes
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import org.ccoin.models.StartMiningRequest
import org.ccoin.models.SubmitMiningRequest
import org.ccoin.services.MiningService
import org.ccoin.services.ValidationService
fun Route.miningRoutes() {
route("/mining") {
/** Start a mining job */
post("/start") {
try {
val request = call.receive<StartMiningRequest>()
// Validate miner address
if (!ValidationService.validateWalletAddress(request.minerAddress)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid miner address format"))
return@post
}
// Validate difficulty if provided
if (request.difficulty != null && !ValidationService.validateMiningDifficulty(request.difficulty)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid mining difficulty"))
return@post
}
val job = MiningService.startMining(request.minerAddress, request.difficulty)
call.respond(HttpStatusCode.Created, job)
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to start mining job")))
}
}
/** Sumit mining result */
post("/submit") {
try {
val request = call.receive<SubmitMiningRequest>()
// Validate miner address
if (!ValidationService.validateWalletAddress(request.minerAddress)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid miner address format"))
return@post
}
// Validate hash format
if (!ValidationService.validateBlockHash(request.hash)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid hash format"))
return@post
}
// Validate previous hash format
if (!ValidationService.validateBlockHash(request.previousHash)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid previous hash format"))
return@post
}
// Validate nonce
if (!ValidationService.validateMiningNonce(request.nonce)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid nonce"))
return@post
}
// Validate timestamp
if (!ValidationService.validateTimestamp(request.timestamp)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid timestamp"))
return@post
}
val block = MiningService.submitMiningResult(
request.minerAddress,
request.nonce,
request.hash,
request.previousHash,
request.timestamp
)
call.respond(HttpStatusCode.Created, block)
} catch (e: Exception) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to (e.message ?: "Mining submission failed")))
}
}
/** Get current mining difficulty */
get("/difficulty") {
try {
val difficulty = MiningService.getCurrentDifficulty()
call.respond(mapOf("difficulty" to difficulty))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to get difficulty")))
}
}
/** Get mining statistics for a miner */
get("/stats/{address}") {
try {
val address = call.parameters["address"] ?: run {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Address parameter required"))
return@get
}
// Validate address format
if (!ValidationService.validateWalletAddress(address)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid address format"))
return@get
}
val stats = MiningService.getMinerStats(address)
call.respond(stats)
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to get miner statistics")))
}
}
/** Get network mining statistics */
get("/network") {
try {
val hashRate = MiningService.getNetworkHashRate()
val averageBlockTime = MiningService.getAverageBlockTime()
val activeMiners = MiningService.getActiveMinersCount()
val difficulty = MiningService.getCurrentDifficulty()
call.respond(mapOf(
"networkHashRate" to hashRate,
"averageBlockTime" to averageBlockTime,
"activeMiners" to activeMiners,
"currentDifficulty" to difficulty
))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to get network statistics")))
}
}
/** Get pending transactions available for mining */
get("/pending-transactions") {
try {
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: 100
if (limit in 0..1000) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Limit must be between 1 and 1000"))
return@get
}
val transactions = MiningService.getPendingTransactionsForMining(limit)
call.respond(mapOf(
"transactions" to transactions,
"count" to transactions.size
))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to get pending transactions")))
}
}
/** Validate mining job */
post("/validate") {
try {
val jobId = call.request.queryParameters["jobId"] ?: run {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Job ID parameter required"))
return@post
}
val hash = call.request.queryParameters["hash"] ?: run {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Hash parameter required"))
return@post
}
val nonce = call.request.queryParameters["nonce"]?.toLongOrNull() ?: run {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Valid nonce parameter required"))
return@post
}
// Validate hash format
if (!ValidationService.validateBlockHash(hash)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid hash format"))
return@post
}
// Validate nonce
if (!ValidationService.validateMiningNonce(nonce)) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid nonce"))
return@post
}
val isValid = MiningService.validateMiningJob(jobId, hash, nonce)
call.respond(mapOf(
"jobId" to jobId,
"hash" to hash,
"nonce" to nonce,
"isValid" to isValid
))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to validate mining job")))
}
}
/** Get mining leaderboard */
get("/leaderboard") {
try {
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: 10
if (limit in 0..100) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Limit must be between 1 and 100"))
return@get
}
// This would need a new service method to get top miners
// For now, return a placeholder response
call.respond(mapOf(
"message" to "Leaderboard endpoint - implementation needed",
"limit" to limit
))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to (e.message ?: "Failed to get mining leaderboard")))
}
}
}
}