Skip to content

Commit

Permalink
Merge pull request #1285 from ergoplatform/v4.0.5
Browse files Browse the repository at this point in the history
Candidate for version 4.0.5
  • Loading branch information
kushti authored Feb 17, 2021
2 parents 56ad381 + b06c431 commit 6ad1132
Show file tree
Hide file tree
Showing 11 changed files with 355 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ To run specific Ergo version `<VERSION>` as a service with custom config `/path/
-e MAX_HEAP=3G \
ergoplatform/ergo:<VERSION> --<networkId> -c /etc/myergo.conf

Available versions can be found on [Ergo Docker image page](https://hub.docker.com/r/ergoplatform/ergo/tags), for example, `v3.3.7`.
Available versions can be found on [Ergo Docker image page](https://hub.docker.com/r/ergoplatform/ergo/tags), for example, `v4.0.5`.

This will connect to the Ergo mainnet or testnet following your configuration passed in `myergo.conf` and network flag `--<networkId>`. Every default config value would be overwritten with corresponding value in `myergo.conf`. `MAX_HEAP` variable can be used to control how much memory can the node consume.

Expand Down
11 changes: 9 additions & 2 deletions ergo-wallet/src/main/scala/org/ergoplatform/wallet/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,17 @@ object Utils {
}
.toIndexedSeq

val dataInputs = IndexedSeq.empty
val outputs = if (changeAmt == 0) {
IndexedSeq(payTo, fee)
} else {
IndexedSeq(payTo, change, fee)
}

new UnsignedErgoLikeTransaction(
unsignedInputs,
IndexedSeq(),
IndexedSeq(payTo, change, fee)
dataInputs,
outputs
)
}

Expand Down
92 changes: 86 additions & 6 deletions 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: "3.3.7"
version: "4.0.5"
title: Ergo Node API
description: API docs for Ergo Node. Models are shared between all Ergo products
contact:
Expand Down Expand Up @@ -396,6 +396,24 @@ components:
address:
$ref: '#/components/schemas/ErgoAddress'

BoxesRequestHolder:
description: Holds request for wallet boxes
type: object
required:
- targetAssets
- targetBalance
properties:
targetAssets:
description: Target assets
type: array
items:
description: Pair of TokenId and Long
type: array
targetBalance:
description: Target balance
type: integer
format: int64

RequestsHolder:
description: Holds many transaction requests and transaction fee
type: object
Expand Down Expand Up @@ -1396,11 +1414,10 @@ components:
levels:
type: array
items:
type: string
description: internal node with direction byte prepended
example: '018b7ae20a4acd23e3f1bf38671ce97103ad96d8f1c780b5e5e865e4873ae16337'
example: ['018b7ae20a4acd23e3f1bf38671ce97103ad96d8f1c780b5e5e865e4873ae16337']

type: array
description: pairs of hash and side of hash
example: ['018b7ae20a4acd23e3f1bf38671ce97103ad96d8f1c780b5e5e865e4873ae16337', 0]
example: [['018b7ae20a4acd23e3f1bf38671ce97103ad96d8f1c780b5e5e865e4873ae16337', 0]]

ProofOfUpcomingTransactions:
type: object
Expand Down Expand Up @@ -2129,6 +2146,38 @@ paths:
schema:
$ref: '#/components/schemas/ApiError'

/blocks/{headerId}/proofFor/{txId}:
get:
summary: Get Merkle proof for transaction
operationId: getProofForTx
tags:
- blocks
parameters:
- in: path
name: headerId
required: true
description: ID of a wanted block transactions
schema:
type: string
- in: path
name: txId
required: true
description: ID of a wanted transaction
schema:
type: string
responses:
'200':
description: Merkle proof object
content:
application/json:
schema:
$ref: '#/components/schemas/MerkleProof'
default:
description: Error
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'

/blocks/lastHeaders/{count}:
get:
Expand Down Expand Up @@ -3252,6 +3301,37 @@ paths:
schema:
$ref: '#/components/schemas/ApiError'

/wallet/boxes/collect:
get:
security:
- ApiKeyAuth: [ api_key ]
summary: Get a list of collected boxes.
operationId: walletBoxesCollect
tags:
- wallet
requestBody:
description: This API method recieves balance and assets, according to which, it's collecting result
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BoxesRequestHolder'
responses:
'200':
description: A list of all collected boxes
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/WalletBox'
default:
description: Error
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'

/wallet/boxes/unspent:
parameters:
- in: query
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ scorex {
bindAddress = "0.0.0.0:9052"

# Hex-encoded Blake2b256 hash of an API key. Should be 64-chars long Base16 string.
apiKeyHash = "1111"
apiKeyHash = null

# Enable/disable CORS support.
# This is an optional param. It would allow cors in case if this setting is set.
Expand All @@ -275,7 +275,7 @@ scorex {
nodeName = "ergo-node"

# Network version send in handshake
appVersion = 3.3.6
appVersion = 4.0.5

# Network agent name. May contain information about client code
# stack, starting from core code-base up to the end graphical interface.
Expand Down
17 changes: 11 additions & 6 deletions src/main/scala/org/ergoplatform/ErgoApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,44 @@ package org.ergoplatform

import java.net.InetSocketAddress

import akka.actor.{ActorRef, PoisonPill, ActorSystem}
import akka.actor.{ActorRef, ActorSystem, PoisonPill}
import akka.http.scaladsl.Http
import akka.stream.SystemMaterializer
import org.ergoplatform.http._
import org.ergoplatform.mining.ErgoMiner.StartMining
import org.ergoplatform.http.api.{ScanApiRoute, _}
import org.ergoplatform.local._
import org.ergoplatform.mining.ErgoMinerRef
import org.ergoplatform.network.{ModeFeature, ErgoNodeViewSynchronizer}
import org.ergoplatform.network.{ErgoNodeViewSynchronizer, ModeFeature}
import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec
import org.ergoplatform.nodeView.{ErgoReadersHolderRef, ErgoNodeViewRef}
import org.ergoplatform.settings.{Args, NetworkType, ErgoSettings}
import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef}
import org.ergoplatform.settings.{Args, ErgoSettings, NetworkType}
import scorex.core.api.http._
import scorex.core.app.{Application, ScorexContext}
import scorex.core.network.NetworkController.ReceivableMessages.ShutdownNetwork
import scorex.core.network.message._
import scorex.core.network.peer.PeerManagerRef
import scorex.core.network.{PeerSynchronizerRef, UPnP, UPnPGateway, PeerFeature, NetworkControllerRef}
import scorex.core.network.{NetworkControllerRef, PeerFeature, PeerSynchronizerRef, UPnP, UPnPGateway}
import scorex.core.settings.ScorexSettings
import scorex.core.utils.NetworkTimeProvider
import scorex.util.ScorexLogging

import scala.concurrent.duration._
import scala.concurrent.{Await, ExecutionContext}
import scala.io.Source
import scala.util.{Success, Failure}
import scala.util.{Failure, Success}

class ErgoApp(args: Args) extends ScorexLogging {

log.info(s"Running with args: $args")

private val ergoSettings: ErgoSettings = ErgoSettings.read(args)

require(ergoSettings.scorexSettings.restApi.apiKeyHash.isDefined, "API key hash must be set")

log.info(s"Working directory: ${ergoSettings.directory}")
log.info(s"Secret directory: ${ergoSettings.walletSettings.secretStorage.secretDir}")

implicit private def settings: ScorexSettings = ergoSettings.scorexSettings

implicit private val actorSystem: ActorSystem = ActorSystem(settings.network.agentName)
Expand Down
16 changes: 16 additions & 0 deletions src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import sigmastate.interpreter._
import sigmastate.interpreter.CryptoConstants.EcPointType
import io.circe.syntax._
import org.ergoplatform.http.api.requests.{CryptoResult, ExecuteRequest, HintExtractionRequest}
import scorex.crypto.authds.{LeafData, Side}
import scorex.crypto.authds.merkle.MerkleProof
import scorex.crypto.hash.Digest
import sigmastate.serialization.OpCodes
import special.sigma.AnyValue

Expand All @@ -42,6 +45,19 @@ trait ApiCodecs extends JsonCodecs {
fromTry(validationResult.toTry)
}

implicit val leafDataEncoder: Encoder[LeafData] = xs => Base16.encode(xs).asJson

implicit val digestEncoder: Encoder[Digest] = x => Base16.encode(x).asJson

implicit val sideEncoder: Encoder[Side] = _.toByte.asJson

implicit def merkleProofEncoder[D <: Digest]: Encoder[MerkleProof[D]] = { proof =>
Json.obj(
"leafData" -> proof.leafData.asJson,
"levels" -> proof.levels.asJson,
)
}

implicit val bigIntEncoder: Encoder[BigInt] = { bigInt =>
JsonNumber.fromDecimalStringUnsafe(bigInt.toString).asJson
}
Expand Down
30 changes: 27 additions & 3 deletions src/main/scala/org/ergoplatform/http/api/BlocksApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import akka.http.scaladsl.server.{Directive, Route}
import akka.pattern.ask
import io.circe.Json
import io.circe.syntax._
import org.ergoplatform.modifiers.history.Header
import org.ergoplatform.modifiers.{ErgoFullBlock, ErgoPersistentModifier}
import org.ergoplatform.modifiers.history.{BlockTransactions, Header}
import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock, ErgoPersistentModifier}
import org.ergoplatform.nodeView.ErgoReadersHolder.GetDataFromHistory
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.settings.{Algos, ErgoSettings}
import scorex.core.NodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
import scorex.core.api.http.ApiError.BadRequest
import scorex.core.api.http.ApiResponse
import scorex.core.settings.RESTApiSettings
import scorex.crypto.authds.merkle.MerkleProof
import scorex.crypto.hash.Digest32
import scorex.util.ModifierId

import scala.concurrent.Future
Expand All @@ -31,6 +33,7 @@ case class BlocksApiRoute(viewHolderRef: ActorRef, readersHolder: ActorRef, ergo
getBlockIdsAtHeightR ~
getBlockHeaderByHeaderIdR ~
getBlockTransactionsByHeaderIdR ~
getProofForTxR ~
getFullBlockByHeaderIdR ~
getModifierByIdR
}
Expand Down Expand Up @@ -63,6 +66,21 @@ case class BlocksApiRoute(viewHolderRef: ActorRef, readersHolder: ActorRef, ergo
private def getModifierById(modifierId: ModifierId): Future[Option[ErgoPersistentModifier]] =
getHistory.map(_.modifierById(modifierId))

private def getProofForTx(headerId: ModifierId, txId: ModifierId): Future[Option[MerkleProof[Digest32]]] =
getModifierById(headerId).flatMap {
case Some(header: Header) =>
val blockTxsId = BlockSection.computeId(
BlockTransactions.modifierTypeId,
headerId,
header.transactionsRoot.asInstanceOf[Array[Byte]]
)
getModifierById(blockTxsId).map {
case Some(txs: BlockTransactions) => txs.proofFor(txId)
case _ => None
}
case _ => Future(None)
}

private def getChainSlice(fromHeight: Int, toHeight: Int): Future[Json] =
getHistory.map { history =>
val maxHeaderOpt = if (toHeight >= 0) {
Expand Down Expand Up @@ -93,7 +111,9 @@ case class BlocksApiRoute(viewHolderRef: ActorRef, readersHolder: ActorRef, ergo
log.info("Received a new valid block through the API: " + block)

viewHolderRef ! LocallyGeneratedModifier(block.header)
block.blockSections.foreach { viewHolderRef ! LocallyGeneratedModifier(_) }
block.blockSections.foreach {
viewHolderRef ! LocallyGeneratedModifier(_)
}

ApiResponse.OK
} else {
Expand All @@ -109,6 +129,10 @@ case class BlocksApiRoute(viewHolderRef: ActorRef, readersHolder: ActorRef, ergo
ApiResponse(getModifierById(id))
}

def getProofForTxR: Route = (modifierId & pathPrefix("proofFor") & modifierId & get) { (headerId, txId) =>
ApiResponse(getProofForTx(headerId, txId))
}

def getLastHeadersR: Route = (pathPrefix("lastHeaders" / IntNumber) & get) { count =>
ApiResponse(getLastHeaders(count))
}
Expand Down
Loading

0 comments on commit 6ad1132

Please sign in to comment.