Skip to content

Commit

Permalink
Merge pull request #1347 from ergoplatform/v4.0.11
Browse files Browse the repository at this point in the history
Candidate for version 4.0.11
  • Loading branch information
kushti authored May 24, 2021
2 parents 9a6057f + cbe4ba2 commit b0a0b6a
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 110 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ COPY benchmarks/build.sbt benchmarks/build.sbt
RUN sbt update
COPY . ./
RUN sbt assembly
RUN mv `find . -name ergo-*.jar` ergo.jar
RUN mv `find target/scala-*/stripped/ -name ergo-*.jar` ergo.jar

FROM openjdk:11-jre-slim
RUN adduser --disabled-password --home /home/ergo --uid 9052 --gecos "ErgoPlatform" ergo && \
Expand Down
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, `v4.0.10`.
Available versions can be found on [Ergo Docker image page](https://hub.docker.com/r/ergoplatform/ergo/tags), for example, `v4.0.11`.

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
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ val circeVersion = "0.13.0"
val akkaVersion = "2.6.10"
val akkaHttpVersion = "10.2.1"

val scorexVersion = "master-7d7d9bb7-SNAPSHOT"
val scorexVersion = "main-a6fe1419-SNAPSHOT"
val sigmaStateVersion = "4.0.3"

// for testing current sigmastate build (see sigmastate-ergo-it jenkins job)
Expand All @@ -56,7 +56,7 @@ libraryDependencies ++= Seq(
"com.iheart" %% "ficus" % "1.4.7",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.google.guava" % "guava" % "21.0",
"com.joefkelley" %% "argyle" % "1.0.0",
"com.github.scopt" %% "scopt" % "4.0.1",

"org.scala-lang.modules" %% "scala-async" % "0.9.7" % "test",
"com.storm-enroute" %% "scalameter" % "0.8.+" % "test",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ object TransactionBuilder {
require(inputs.distinct.size == inputs.size, s"There should be no duplicate inputs")
}


/** Creates unsigned transaction from given inputs and outputs adding outputs with miner's fee and change
* Runs required checks ensuring that resulted transaction will be successfully validated by a node.
*
* @param inputs - input boxes
* @param dataInputs - data inputs
* @param inputs - input boxes
* @param dataInputs - data inputs
* @param outputCandidates - output candidate boxes
* @param currentHeight - current height (used in miner's fee box and change box)
* @param feeAmount - fee amount to put in miner's fee box
* @param changeAddress - address where to send change from the input boxes
* @param minChangeValue - minimum change value to send, otherwise add to miner's fee
* @param currentHeight - current height (used in miner's fee box and change box)
* @param createFeeOutput - optional fee amount to put in a new miner's fee box, which will be
* created by this method. If None, then feeOut is not created.
* @param changeAddress - address where to send change from the input boxes
* @param minChangeValue - minimum change value to send, otherwise add to miner's fee
* @param minerRewardDelay - reward delay to encode in miner's fee box
* @return unsigned transaction
*/
Expand All @@ -68,7 +68,7 @@ object TransactionBuilder {
dataInputs: IndexedSeq[DataInput],
outputCandidates: Seq[ErgoBoxCandidate],
currentHeight: Int,
feeAmount: Long,
createFeeOutput: Option[Long],
changeAddress: ErgoAddress,
minChangeValue: Long,
minerRewardDelay: Int,
Expand All @@ -80,7 +80,8 @@ object TransactionBuilder {

// TODO: implement all appropriate checks from ErgoTransaction.validateStatefull

require(feeAmount > 0, s"expected fee amount > 0, got $feeAmount")
val feeAmount = createFeeOutput.getOrElse(0L)
require(createFeeOutput.fold(true)(_ > 0), s"expected fee amount > 0, got $feeAmount")
val inputTotal = inputs.map(_.value).sum
val outputSum = outputCandidates.map(_.value).sum
val outputTotal = outputSum + feeAmount
Expand Down Expand Up @@ -110,17 +111,24 @@ object TransactionBuilder {
val changeBoxes = selection.changeBoxes
val changeBoxesHaveTokens = changeBoxes.exists(_.tokens.nonEmpty)

val noChange = changeAmt < minChangeValue && !changeBoxesHaveTokens

// if computed changeAmt is too small give it to miner as tips
val actualFee = if (noChange) feeAmount + changeAmt else feeAmount
val feeOut = new ErgoBoxCandidate(
actualFee,
ErgoScriptPredef.feeProposition(minerRewardDelay),
currentHeight
)
val changeGoesToFee = changeAmt < minChangeValue && !changeBoxesHaveTokens

require(!changeGoesToFee || (changeAmt == 0 || createFeeOutput.isDefined),
s"""When change=$changeAmt < minChangeValue=$minChangeValue it is added to miner's fee,
|in this case createFeeOutput should be defined
|""".stripMargin)

val feeOutOpt = createFeeOutput.map { fee =>
// if computed changeAmt is too small give it to miner as tips
val actualFee = if (changeGoesToFee) fee + changeAmt else fee
new ErgoBoxCandidate(
actualFee,
ErgoScriptPredef.feeProposition(minerRewardDelay),
currentHeight
)
}

val addedChangeOut = if (!noChange) {
val addedChangeOut = if (!changeGoesToFee) {
val script = changeAddress.script
changeBoxes.map { cb =>
new ErgoBoxCandidate(cb.value, script, currentHeight, tokensMapToColl(cb.tokens))
Expand All @@ -129,7 +137,7 @@ object TransactionBuilder {
Seq()
}

val finalOutputCandidates = outputCandidates ++ Seq(feeOut) ++ addedChangeOut
val finalOutputCandidates = outputCandidates ++ feeOutOpt ++ addedChangeOut

new UnsignedErgoLikeTransaction(
inputs.map(b => new UnsignedInput(b.id)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import sigmastate.Values.SigmaPropValue
import sigmastate.eval._
import sigmastate.eval.Extensions._
import sigmastate.helpers.TestingHelpers._
import sigmastate.utils.Helpers._
import org.ergoplatform._
import org.scalatest.Matchers
import org.ergoplatform.ErgoBox.TokenId
import org.ergoplatform.wallet.TokensMap

import scala.util.{Success, Try}
import scala.util.{Success, Try, Failure}
import scorex.crypto.hash.Digest32
import org.ergoplatform.wallet.mnemonic.Mnemonic
import org.ergoplatform.wallet.secrets.ExtendedSecretKey
Expand Down Expand Up @@ -51,17 +52,17 @@ class TransactionBuilderSpec extends WalletTestHelpers with Matchers {

def transaction(inputBox: ErgoBox,
outBox: ErgoBoxCandidate,
fee: Option[Long] = Some(minBoxValue),
burnTokens: TokensMap = Map.empty): Try[UnsignedErgoLikeTransaction] = {
val ins = IndexedSeq(inputBox)
val outs = IndexedSeq(outBox)
val changeAddress = P2PKAddress(rootSecret.privateInput.publicImage)
val fee = minBoxValue
val res = buildUnsignedTx(
inputs = ins,
dataInputs = IndexedSeq(),
outputCandidates = outs,
currentHeight = currentHeight,
feeAmount = fee,
createFeeOutput = fee,
changeAddress = changeAddress,
minChangeValue = minChangeValue,
minerRewardDelay = minerRewardDelay,
Expand Down Expand Up @@ -100,4 +101,28 @@ class TransactionBuilderSpec extends WalletTestHelpers with Matchers {
val remainingTokens = Map(tid1 -> 600L, tid2 -> 1200L)
TransactionBuilder.collTokensToMap(out2.additionalTokens) shouldBe remainingTokens
}

property("no fees") {
val inputBox = box(minBoxValue)
val tokenId = Digest32 @@ inputBox.id
val outBox = boxCandidate(minBoxValue, Seq(tokenId -> 100L))
val res = transaction(inputBox, outBox, fee = None)

res shouldBe a[Success[_]]
val tx = res.get
tx.outputCandidates.size shouldBe 1
tx.outputCandidates(0) shouldEqual outBox
}

property("change goes to fee, but no outFee box") {
val inputBox = box(minBoxValue + minBoxValue / 2)
val tokenId = Digest32 @@ inputBox.id
val outBox = boxCandidate(minBoxValue, Seq(tokenId -> 100L))
val res = transaction(inputBox, outBox, fee = None)

assertExceptionThrown(
res.getOrThrow,
t => t.getMessage.contains("createFeeOutput should be defined"))
}

}
2 changes: 1 addition & 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: "4.0.10"
version: "4.0.11"
title: Ergo Node API
description: API docs for Ergo Node. Models are shared between all Ergo products
contact:
Expand Down
8 changes: 8 additions & 0 deletions src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,14 @@ ergo {
}
}

akka {
http {
server {
request-timeout = 1 minute
}
}
}

scorex {

# Execution context for all tasks, except of akka actors.
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/mainnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ scorex {
network {
magicBytes = [1, 0, 2, 4]
bindAddress = "0.0.0.0:9030"
nodeName = "ergo-mainnet-4.0.10"
nodeName = "ergo-mainnet-4.0.11"
nodeName = ${?NODENAME}
knownPeers = [
"213.239.193.208:9030",
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/testnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ ergo {

scorex {
network {
magicBytes = [2, 0, 0, 1]
magicBytes = [2, 0, 0, 2]
bindAddress = "0.0.0.0:9020"
nodeName = "ergo-testnet-4.0.10"
nodeName = "ergo-testnet-4.0.11"
nodeName = ${?NODENAME}
knownPeers = [
"213.239.193.208:9020"
"213.239.193.208:9020",
"37.156.20.158:9020"
]
}
restApi {
Expand Down
33 changes: 24 additions & 9 deletions src/main/scala/org/ergoplatform/ErgoApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class ErgoApp(args: Args) extends ScorexLogging {
// Useful for local blockchains (devnet)
if (ergoSettings.nodeSettings.mining && ergoSettings.nodeSettings.offlineGeneration) {
require(minerRefOpt.isDefined, "Miner does not exist but mining = true in config")
log.info(s"Starting mining with offlineGeneration")
minerRefOpt.get ! StartMining
}

Expand Down Expand Up @@ -192,16 +193,30 @@ class ErgoApp(args: Args) extends ScorexLogging {

object ErgoApp extends ScorexLogging {

import com.joefkelley.argyle._

val argParser: Arg[Args] = (
optional[String]("--config", "-c") and
optionalOneOf[NetworkType](NetworkType.all.map(x => s"--${x.verboseName}" -> x): _*)
).to[Args]
val argParser = new scopt.OptionParser[Args]("ergo") {
opt[String]("config")
.abbr("c")
.action((x, c) => c.copy(userConfigPathOpt = Some(x)))
.text("location of ergo node configuration")
.optional()
opt[Unit]("devnet")
.action((_, c) => c.copy(networkTypeOpt = Some(NetworkType.DevNet)))
.text("set network to devnet")
.optional()
opt[Unit]("testnet")
.action((_, c) => c.copy(networkTypeOpt = Some(NetworkType.TestNet)))
.text("set network to testnet")
.optional()
opt[Unit]("mainnet")
.action((_, c) => c.copy(networkTypeOpt = Some(NetworkType.MainNet)))
.text("set network to mainnet")
.optional()
help("help").text("prints this usage text")
}

def main(args: Array[String]): Unit = argParser.parse(args) match {
case Success(argsParsed) => new ErgoApp(argsParsed).run()
case Failure(e) => throw e
def main(args: Array[String]): Unit = argParser.parse(args, Args()) match {
case Some(argsParsed) => new ErgoApp(argsParsed).run()
case None => // Error message will be displayed when arguments are bad
}

def forceStopApplication(code: Int = 1): Nothing = sys.exit(code)
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ case class MiningApiRoute(miner: ActorRef,
*/
def candidateR: Route = (path("candidate") & pathEndOrSingleSlash & get) {
val prepareCmd = ErgoMiner.PrepareCandidate(Seq.empty)
val candidateF = (miner ? prepareCmd).mapTo[Future[WorkMessage]].flatten
val candidateF = miner.askWithStatus(prepareCmd).mapTo[WorkMessage]
ApiResponse(candidateF)
}

Expand All @@ -49,13 +49,13 @@ case class MiningApiRoute(miner: ActorRef,
& post & entity(as[Seq[ErgoTransaction]]) & withAuth) { txs =>

val prepareCmd = ErgoMiner.PrepareCandidate(txs)
val candidateF = (miner ? prepareCmd).mapTo[Future[WorkMessage]].flatten
val candidateF = miner.askWithStatus(prepareCmd).mapTo[WorkMessage]
ApiResponse(candidateF)
}

def solutionR: Route = (path("solution") & post & entity(as[AutolykosSolution])) { solution =>
val result = if (ergoSettings.nodeSettings.useExternalMiner) {
(miner ? solution).mapTo[Future[Unit]].flatten
miner.askWithStatus(solution).mapTo[Unit]
} else {
Future.failed(new Exception("External miner support is inactive"))
}
Expand Down
Loading

0 comments on commit b0a0b6a

Please sign in to comment.