Skip to content

Commit

Permalink
Merge pull request #126 from ltonetwork/submit-transaction
Browse files Browse the repository at this point in the history
New API endpoint to sign and broadcast
  • Loading branch information
jasny authored Mar 16, 2022
2 parents fa44019 + 0ba202f commit 7f3d5af
Show file tree
Hide file tree
Showing 41 changed files with 390 additions and 366 deletions.
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,21 @@ docker run -p 6869:6869 -p 6863:6863 -e LTO_NETWORK=TESTNET -e LTO_HEAP_SIZE=2g

**You can run the container with these environment variables:**

|Env variable |Description |
|-----------------------------|--------------|
|`LTO_WALLET_SEED` |Plain text seed for node wallet. Container converts it to base58. |
|`LTO_WALLET_SEED_BASE58` |Base58 encoded seed. (Supersedes LTO_WALLET_SEED) |
|`LTO_WALLET_PASSWORD` |Password for wallet file. |
|`LTO_API_KEY` |ApiKey used for the rest api authentication |
|`LTO_NETWORK` |Available values are `MAINNET`, `TESTNET` and `CUSTOM`. (Default: `MAINNET`) |
|`LTO_LOG_LEVEL` |Node logging level, available values: `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. |
|`LTO_HEAP_SIZE` |Java Heap Size limit in -X Command-line Options notation (`-Xms=[your value]`). More details [here](https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html) |
|`LTO_CONFIG_FILE` |Path to your LTO Configuration file. |
|`LTO_DECLARED_ADDRESS` |String with IP address and port to send as external address during handshake. Could be set automatically if UPnP is enabled. If `declared-address` is set, which is the common scenario for nodes running in the cloud, the node will just listen to incoming connections on `bind-address:port` and broadcast its `declared-address` to its peers.|
|`LTO_NODE_NAME` |Node name used in the handshake when connecting to other nodes|
|`LTO_ENABLE_REST_API` |To enable the REST API. (For `MAINNET` default is `false` for `TESTNET` default is `true`|
|`LTO_FEATURES` |Features you wish to vote. E.g. set to 4 to start voting for the Smart Accounts feature. You can also vote for multiple features at by comma seperating them (e.g. 4,5)|
| Env variable | Description |
|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `LTO_WALLET_SEED` | Plain text seed for node wallet. Container converts it to base58. |
| `LTO_WALLET_SEED_BASE58` | Base58 encoded seed. (Supersedes LTO_WALLET_SEED) |
| `LTO_WALLET_PASSWORD` | Password for wallet file. |
| `LTO_API_KEY` | ApiKey used for the rest api authentication |
| `LTO_NETWORK` | Available values are `MAINNET`, `TESTNET` and `CUSTOM`. (Default: `MAINNET`) |
| `LTO_LOG_LEVEL` | Node logging level, available values: `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. |
| `LTO_HEAP_SIZE` | Java Heap Size limit in -X Command-line Options notation (`-Xms=[your value]`). More details [here](https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html) |
| `LTO_CONFIG_FILE` | Path to your LTO Configuration file. |
| `LTO_DECLARED_ADDRESS` | String with IP address and port to send as external address during handshake. Could be set automatically if UPnP is enabled. If `declared-address` is set, which is the common scenario for nodes running in the cloud, the node will just listen to incoming connections on `bind-address:port` and broadcast its `declared-address` to its peers. |
| `LTO_NODE_NAME` | Node name used in the handshake when connecting to other nodes |
| `LTO_ENABLE_REST_API` | To enable the REST API. (For `MAINNET` default is `false` for `TESTNET` default is `true`) |
| `LTO_ENABLE_MINING` | To enable PoS mining (default is `true`) |
| `LTO_FEATURES` | Features you wish to vote. E.g. set to 4 to start voting for the Smart Accounts feature. You can also vote for multiple features at by comma seperating them (e.g. 4,5) |

**Note: All variables are optional.**

Expand Down
2 changes: 1 addition & 1 deletion e2e/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
lto~=1.2.1
lto~=1.2.3
behave~=1.2.6
polling~=0.3.2
3 changes: 0 additions & 3 deletions lto-mainnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ lto {

# Port to listen to REST API requests
port = 6869

# Hash of API key string
api-key-hash = "GfSz71FEbo3U3aQv9DoJ5N1nNx8zvBzWwrcNjztX3qmP"
}

checkpoints.public-key = "4S3nfAPBRJcqHs41gb88fDfFUwbPR4NmYuCch1V8wY7d"
Expand Down
3 changes: 0 additions & 3 deletions lto-testnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@ lto {

# Port to listen to REST API requests
port = 6869

# Hash of API key string
api-key-hash = "BgLRrVvDTau3j4Fz4YMzUUA31FKkYWoYX73GCm67rNRz"
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ lto {
port = 6869

# Hash of API key string
api-key-hash = "AowtuqFQgbp29uzbHFntQjiwxWAUshjyUjhxhY967J6s"
api-key-hash = "-"

# Enable/disable CORS support
cors = yes
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/com/ltonetwork/Version.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ package com.ltonetwork
// In case of not updating the version nodes build from headless sources will fail to connect to newer versions

object Version {
val VersionString = "1.4.0"
val VersionTuple: (Int, Int, Int) = (1, 4, 0)
val VersionString = "1.5.x"
val VersionTuple: (Int, Int, Int) = (1, 5, 0)
}
2 changes: 1 addition & 1 deletion src/main/scala/com/ltonetwork/api/AddressApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ case class AddressApiRoute(settings: RestAPISettings,
ToResponseMarshallable(result)
}

private def verifyPath(address: String, decode: Boolean) = withAuth {
private def verifyPath(address: String, decode: Boolean) = {
json[SignedMessage] { m =>
if (Address.fromString(address).isLeft) {
InvalidAddress
Expand Down
9 changes: 5 additions & 4 deletions src/main/scala/com/ltonetwork/api/ApiRoute.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.ltonetwork.api

import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.headers.{Authorization, OAuth2BearerToken}
import akka.http.scaladsl.server._
import com.ltonetwork.crypto
import com.ltonetwork.http.{ApiMarshallers, PlayJsonException, api_key, deprecated_api_key}
import com.ltonetwork.http.{ApiKey, ApiMarshallers, PlayJsonException}
import com.ltonetwork.settings.RestAPISettings
import com.ltonetwork.utils.Base58
import play.api.libs.json.Reads
Expand All @@ -28,10 +29,10 @@ trait ApiRoute extends Directives with CommonApiFunctions with ApiMarshallers {
}

def withAuth: Directive0 = apiKeyHash.fold[Directive0](complete(ApiKeyNotValid)) { hashFromSettings =>
optionalHeaderValueByType(api_key).flatMap {
case Some(k) if crypto.secureHash(k.value.getBytes()).sameElements(hashFromSettings) => pass
optionalHeaderValueByType(Authorization).map(_.map(_.credentials)).flatMap {
case Some(c: OAuth2BearerToken) if crypto.secureHash(c.token.getBytes()).sameElements(hashFromSettings) => pass
case _ =>
optionalHeaderValueByType(deprecated_api_key).flatMap {
optionalHeaderValueByType(ApiKey).flatMap {
case Some(k) if crypto.secureHash(k.value.getBytes()).sameElements(hashFromSettings) => pass
case _ => complete(ApiKeyNotValid)
}
Expand Down
22 changes: 13 additions & 9 deletions src/main/scala/com/ltonetwork/api/CompositeHttpService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package com.ltonetwork.api
import akka.actor.ActorSystem
import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.http.scaladsl.model.{HttpEntity, HttpRequest, MediaTypes, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.RouteResult.Complete
import akka.http.scaladsl.server.directives.{DebuggingDirectives, LoggingMagnet}
import akka.http.scaladsl.server.{Directive0, Route, RouteResult}
import com.github.swagger.akka.CustomMediaTypes
import com.github.swagger.akka.SwaggerHttpService.apiDocsBase
import com.ltonetwork.api.swagger.SwaggerDocService
import com.ltonetwork.settings.RestAPISettings
import com.ltonetwork.utils.ScorexLogging
Expand All @@ -22,24 +24,26 @@ case class CompositeHttpService(system: ActorSystem, apiTypes: Set[Class[_]], ro
respondWithHeader(`Access-Control-Allow-Origin`.*)
else pass

private val headers: scala.collection.immutable.Seq[String] = scala.collection.immutable.Seq("Authorization",
"Content-Type",
"X-Requested-With",
"Timestamp",
"Signature") ++
(if (settings.apiKeyDifferentHost) Seq("api_key", "X-API-Key") else Seq.empty[String])
private val headers: scala.collection.immutable.Seq[String] =
scala.collection.immutable.Seq("Authorization", "Content-Type", "X-Requested-With", "Timestamp", "Signature") ++
(if (settings.apiKeyDifferentHost) Seq("X-API-Key") else Seq.empty[String])

val compositeRoute: Route =
withCors(routes.map(_.route).reduce(_ ~ _)) ~
swaggerService.routes ~
(pathEndOrSingleSlash | path("swagger")) {
redirect("/api-docs/index.html", StatusCodes.PermanentRedirect)
} ~
pathPrefix("api-docs") {
pathEndOrSingleSlash {
redirect("/api-docs/index.html", StatusCodes.PermanentRedirect)
} ~
getFromResourceDirectory("swagger-ui")
path("swagger.json") {
complete(HttpEntity(MediaTypes.`application/json`, swaggerService.swaggerJson))
} ~
path("swagger.yaml") {
complete(HttpEntity(CustomMediaTypes.`text/vnd.yaml`, swaggerService.swaggerYaml))
} ~
getFromResourceDirectory("swagger-ui")
} ~ options {
respondWithDefaultHeaders(`Access-Control-Allow-Credentials`(true),
`Access-Control-Allow-Headers`(headers),
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/com/ltonetwork/api/PeersApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, ExampleObject, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.{ApiResponse, ApiResponses}
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.ws.rs.{GET, POST, Path}
import play.api.libs.json._
Expand Down Expand Up @@ -90,6 +91,7 @@ case class PeersApiRoute(settings: RestAPISettings,
@Operation(
summary = "Connect to peer"
)
@SecurityRequirement(name = "bearerAuth")
@RequestBody(
description = "Json with data",
content = Array(
Expand Down Expand Up @@ -149,6 +151,7 @@ case class PeersApiRoute(settings: RestAPISettings,
@Operation(
summary = "Remove all blacklisted peers"
)
@SecurityRequirement(name = "bearerAuth")
@ApiResponses(
Array(
new ApiResponse(responseCode = "200", description = "200")
Expand Down
Loading

0 comments on commit 7f3d5af

Please sign in to comment.