Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Candidate for 5.0.25 release #2189

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ local.conf
.vscode/
project/metals.sbt
null/
out/

# scala worksheets
*.worksheet.sc
113 changes: 64 additions & 49 deletions ergo-core/src/main/scala/org/ergoplatform/settings/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,67 +12,81 @@ import scala.concurrent.duration._

case class LoggingSettings(level: String)

case class RESTApiSettings(bindAddress: InetSocketAddress,
apiKeyHash: Option[String],
corsAllowedOrigin: Option[String],
timeout: FiniteDuration,
publicUrl: Option[URL])
case class RESTApiSettings(
bindAddress: InetSocketAddress,
apiKeyHash: Option[String],
corsAllowedOrigin: Option[String],
timeout: FiniteDuration,
publicUrl: Option[URL]
)

case class NetworkSettings(nodeName: String,
addedMaxDelay: Option[FiniteDuration],
localOnly: Boolean,
knownPeers: Seq[InetSocketAddress],
bindAddress: InetSocketAddress,
maxConnections: Int,
connectionTimeout: FiniteDuration,
upnpEnabled: Boolean,
upnpGatewayTimeout: Option[FiniteDuration],
upnpDiscoverTimeout: Option[FiniteDuration],
declaredAddress: Option[InetSocketAddress],
handshakeTimeout: FiniteDuration,
deliveryTimeout: FiniteDuration,
maxDeliveryChecks: Int,
appVersion: String,
agentName: String,
desiredInvObjects: Int,
syncInterval: FiniteDuration,
syncStatusRefresh: FiniteDuration,
syncIntervalStable: FiniteDuration,
syncStatusRefreshStable: FiniteDuration,
inactiveConnectionDeadline: FiniteDuration,
syncTimeout: Option[FiniteDuration],
controllerTimeout: Option[FiniteDuration],
maxModifiersCacheSize: Int,
magicBytes: Array[Byte],
getPeersInterval: FiniteDuration,
maxPeerSpecObjects: Int,
temporalBanDuration: FiniteDuration,
penaltySafeInterval: FiniteDuration,
penaltyScoreThreshold: Int,
peerEvictionInterval: FiniteDuration,
peerDiscovery: Boolean)

case class ScorexSettings(dataDir: File,
logDir: File,
logging: LoggingSettings,
network: NetworkSettings,
restApi: RESTApiSettings)
case class NetworkSettings(
nodeName: String,
addedMaxDelay: Option[FiniteDuration],
localOnly: Boolean,
knownPeers: Seq[InetSocketAddress],
bannedPeers: Seq[InetSocketAddress],
bindAddress: InetSocketAddress,
maxConnections: Int,
connectionTimeout: FiniteDuration,
upnpEnabled: Boolean,
upnpGatewayTimeout: Option[FiniteDuration],
upnpDiscoverTimeout: Option[FiniteDuration],
declaredAddress: Option[InetSocketAddress],
handshakeTimeout: FiniteDuration,
deliveryTimeout: FiniteDuration,
maxDeliveryChecks: Int,
appVersion: String,
agentName: String,
desiredInvObjects: Int,
syncInterval: FiniteDuration,
syncStatusRefresh: FiniteDuration,
syncIntervalStable: FiniteDuration,
syncStatusRefreshStable: FiniteDuration,
inactiveConnectionDeadline: FiniteDuration,
syncTimeout: Option[FiniteDuration],
controllerTimeout: Option[FiniteDuration],
maxModifiersCacheSize: Int,
magicBytes: Array[Byte],
getPeersInterval: FiniteDuration,
maxPeerSpecObjects: Int,
temporalBanDuration: FiniteDuration,
penaltySafeInterval: FiniteDuration,
penaltyScoreThreshold: Int,
peerEvictionInterval: FiniteDuration,
peerDiscovery: Boolean
)

case class ScorexSettings(
dataDir: File,
logDir: File,
logging: LoggingSettings,
network: NetworkSettings,
restApi: RESTApiSettings
)

object ScorexSettings extends ScorexLogging with SettingsReaders {

protected val configPath: String = "scorex"

def readConfigFromPath(userConfigPath: Option[String], configPath: String): Config = {

val maybeConfigFile: Option[File] = userConfigPath.map(filename => new File(filename)).filter(_.exists())
.orElse(userConfigPath.flatMap(filename => Option(getClass.getClassLoader.getResource(filename))).
map(r => new File(r.toURI)).filter(_.exists()))
val maybeConfigFile: Option[File] = userConfigPath
.map(filename => new File(filename))
.filter(_.exists())
.orElse(
userConfigPath
.flatMap(filename => Option(getClass.getClassLoader.getResource(filename)))
.map(r => new File(r.toURI))
.filter(_.exists())
)

val config = maybeConfigFile match {
// if no user config is supplied, the library will handle overrides/application/reference automatically
case None =>
log.warn("NO CONFIGURATION FILE WAS PROVIDED. STARTING WITH DEFAULT SETTINGS FOR TESTNET!")
log.warn(
"NO CONFIGURATION FILE WAS PROVIDED. STARTING WITH DEFAULT SETTINGS FOR TESTNET!"
)
ConfigFactory.load()
// application config needs to be resolved wrt both system properties *and* user-supplied config.
case Some(file) =>
Expand All @@ -96,7 +110,8 @@ object ScorexSettings extends ScorexLogging with SettingsReaders {
}

def fromConfig(config: Config): ScorexSettings = {
config.as[ScorexSettings](configPath)
config
.as[ScorexSettings](configPath)
.ensuring(_.network.magicBytes.length == MagicLength)
}
}
2 changes: 1 addition & 1 deletion src/main/resources/api/openapi-ai.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: "3.0.2"

info:
version: "5.0.24"
version: "5.0.25"
title: Ergo Node API
description: Specification of Ergo Node API for ChatGPT plugin.
The following endpoints supported
Expand Down
54 changes: 53 additions & 1 deletion src/main/resources/api/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: "3.0.2"

info:
version: "5.0.24"
version: "5.0.25"
title: Ergo Node API
description: API docs for Ergo Node. Models are shared between all Ergo products
contact:
Expand Down Expand Up @@ -3261,6 +3261,58 @@ paths:
schema:
$ref: '#/components/schemas/ApiError'

/transactions/unconfirmed/transactionIds:
get:
summary: Get list of unconfirmed transactions ids
operationId: getUnconfirmedTxIds
tags:
- transactions
responses:
'200':
description: List of unconfirmed transaction ids
content:
application/json:
schema:
type: array
items:
type: string
default:
description: Error
content:
application/json:
schema:
$ref: '#/components/schema/ApiError'

/transactions/unconfirmed/byTransactionIds:
post:
summary: Get list of unconfirmed transactions by their ids
operationId: getUnconfirmedTxsByIds
tags:
- transactions
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
type: string
responses:
'200':
description: List of unconfirmed transaction ids
content:
application/json:
schema:
type: array
items:
type: string
default:
description: Error
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'

/transactions/unconfirmed/byErgoTree:
parameters:
- in: query
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ scorex {
nodeName = "ergo-node"

# Network protocol version to be sent in handshakes
appVersion = 5.0.24
appVersion = 5.0.25

# Network agent name. May contain information about client code
# stack, starting from core code-base up to the end graphical interface.
Expand Down Expand Up @@ -498,6 +498,9 @@ scorex {
# A list of `IP:port` pairs of well known nodes.
knownPeers = []

# A list of `IP:port` pairs peers that will be permanently banned
bannedPeers = []

# Interval between GetPeers messages to be send by our node to a random one
getPeersInterval = 2m

Expand Down
11 changes: 9 additions & 2 deletions src/main/scala/org/ergoplatform/http/api/InfoApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import akka.http.scaladsl.model.ContentTypes
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import io.circe.syntax._
import io.circe.Json
import org.ergoplatform.local.ErgoStatsCollector.{GetNodeInfo, NodeInfo}
import org.ergoplatform.settings.RESTApiSettings
import scorex.core.api.http.ApiResponse
Expand All @@ -19,8 +20,14 @@ case class InfoApiRoute(statsCollector: ActorRef,

override val route: Route = {
(path("info") & get) {
val timeJson = Map("currentTime" -> System.currentTimeMillis().asJson).asJson
ApiResponse((statsCollector ? GetNodeInfo).mapTo[NodeInfo].map(_.asJson.deepMerge(timeJson)))
val timeJson = Map(
"currentTime" -> System.currentTimeMillis().asJson
).asJson
ApiResponse((statsCollector ? GetNodeInfo).mapTo[NodeInfo].map { nodeInfo =>
nodeInfo.asJson.deepMerge(timeJson).deepMerge(Json.obj(
"lastMemPoolUpdateTime" -> nodeInfo.lastMemPoolUpdateTime.asJson
))
})
} ~
(path(".well-known" / "ai-plugin.json") & get) {
getFromResource(".well-known/ai-plugin.json", ContentTypes.`application/json`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ case class TransactionsApiRoute(readersHolder: ActorRef,
getUnconfirmedOutputByBoxIdR ~
getUnconfirmedInputByBoxIdR ~
getUnconfirmedTxsByErgoTreeR ~
getUnconfirmedTxIdsR ~
getUnconfirmedTxByIdR ~
getUnconfirmedTxsByIdsR ~
getUnconfirmedTransactionsR ~
unconfirmedContainsR ~
sendTransactionR ~
Expand Down Expand Up @@ -167,6 +169,29 @@ case class TransactionsApiRoute(readersHolder: ActorRef,
ApiResponse(getMemPool.map(_.modifierById(modifierId)))
}

/** Get list of unconfirmed transaction ids */
def getUnconfirmedTxIdsR: Route =
(pathPrefix("unconfirmed" / "transactionIds") & get) {
ApiResponse(getMemPool.map(_.getAll.map(_.id)))
}

/** Post list of unconfirmed transaction ids and check if they are in the mempool */
def getUnconfirmedTxsByIdsR: Route =
(pathPrefix("unconfirmed" / "byTransactionIds") & post & entity(as[Json])) { txIds =>
txIds.as[List[String]] match {
case Left(ex) =>
ApiError(StatusCodes.BadRequest, ex.getMessage())
case Right(ids) =>
ApiResponse(
getMemPool.map { pool =>
pool.getAll
.filter(tx => ids.contains(tx.id))
.map(_.id)
}
)
}
}

/** Collect all transactions which inputs or outputs contain given ErgoTree hex */
def getUnconfirmedTxsByErgoTreeR: Route =
(pathPrefix("unconfirmed" / "byErgoTree") & post & entity(as[Json]) & txPaging) { case (body, offset, limit) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class ErgoStatsCollector(readersHolder: ActorRef,
None,
launchTime = System.currentTimeMillis(),
lastIncomingMessageTime = System.currentTimeMillis(),
lastMemPoolUpdateTime = System.currentTimeMillis(),
None,
LaunchParameters,
eip27Supported = true,
Expand Down Expand Up @@ -100,6 +101,7 @@ class ErgoStatsCollector(readersHolder: ActorRef,

private def onMempoolChanged: Receive = {
case ChangedMempool(p) =>
nodeInfo = nodeInfo.copy(lastMemPoolUpdateTime = System.currentTimeMillis())
nodeInfo = nodeInfo.copy(unconfirmedCount = p.size)
}

Expand Down Expand Up @@ -171,6 +173,7 @@ object ErgoStatsCollector {
* @param maxPeerHeight - maximum block height of connected peers
* @param launchTime - when the node was launched (in Java time format, basically, UNIX time * 1000)
* @param lastIncomingMessageTime - when the node received last p2p message (in Java time)
* @param lastMemPoolUpdateTime - when the mempool was last updated (in Java time)
* @param genesisBlockIdOpt - header id of genesis block
* @param parameters - array with network parameters at the moment
* @param eip27Supported - whether EIP-27 locked in
Expand All @@ -193,6 +196,7 @@ object ErgoStatsCollector {
maxPeerHeight : Option[Int],
launchTime: Long,
lastIncomingMessageTime: Long,
lastMemPoolUpdateTime: Long,
genesisBlockIdOpt: Option[String],
parameters: Parameters,
eip27Supported: Boolean,
Expand Down Expand Up @@ -227,6 +231,7 @@ object ErgoStatsCollector {
"peersCount" -> ni.peersCount.asJson,
"launchTime" -> ni.launchTime.asJson,
"lastSeenMessageTime" -> ni.lastIncomingMessageTime.asJson,
"lastMemPoolUpdateTime" -> ni.lastMemPoolUpdateTime.asJson,
"genesisBlockId" -> ni.genesisBlockIdOpt.asJson,
"parameters" -> ni.parameters.asJson,
"eip27Supported" -> ni.eip27Supported.asJson,
Expand Down
Loading
Loading