Skip to content

Commit

Permalink
NODE-2628 Use valid default address in /utils/evaluate (#3913)
Browse files Browse the repository at this point in the history
  • Loading branch information
phearnot authored Nov 9, 2023
1 parent 069e969 commit 7e02801
Show file tree
Hide file tree
Showing 36 changed files with 421 additions and 387 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class WavesEnvironmentRebenchmark {
@Benchmark
def biggestDataEntries(bh: Blackhole, st: St): Unit = {
val address = Recipient.Address(
ByteStr(Address.fromString("3PFfUN4dRAyMN4nxYayES1CRZHJjS8JVCHf").explicitGet().bytes)
ByteStr(Address.fromString("3PFfUN4dRAyMN4nxYayES1CRZHJjS8JVCHf", None).explicitGet().bytes)
)
val checkBinaryOrString = Random.nextBoolean()
if (checkBinaryOrString) {
Expand All @@ -139,7 +139,7 @@ object WavesEnvironmentRebenchmark {
lazy val allAliases: Vector[Alias] = {
val builder = Vector.newBuilder[Alias]
db.iterateOver(KeyTags.AddressIdOfAlias) { e =>
builder += Alias.fromBytes(e.getKey.drop(2)).explicitGet()
builder += Alias.fromBytes(e.getKey.drop(2), None).explicitGet()
}
builder.result()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ object StateUpdate {
}
}

private lazy val WavesAlias = Alias.fromString("alias:W:waves").explicitGet()
private lazy val WavesAddress = Address.fromString("3PGd1eQR8EhLkSogpmu9Ne7hSH1rQ5ALihd").explicitGet()
private lazy val WavesAlias = Alias.fromString("alias:W:waves", Some('W'.toByte)).explicitGet()
private lazy val WavesAddress = Address.fromString("3PGd1eQR8EhLkSogpmu9Ne7hSH1rQ5ALihd", Some('W'.toByte)).explicitGet()

def atomic(blockchainBeforeWithMinerReward: Blockchain, diff: Diff): StateUpdate = {
val blockchain = blockchainBeforeWithMinerReward
Expand Down
6 changes: 2 additions & 4 deletions node-it/src/test/scala/com/wavesplatform/it/Docker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class Docker(
// Exclude disconnected
client.inspectContainer(node.containerId).networkSettings().networks().isEmpty
}
.map(_.containerNetworkAddress)
.map(_.networkAddress)
.toSeq
}

Expand Down Expand Up @@ -627,9 +627,7 @@ object Docker {

override val apiKey = "integration-test-rest-api"

override def networkAddress: InetSocketAddress = nodeInfo.hostNetworkAddress

def containerNetworkAddress: InetSocketAddress = nodeInfo.containerNetworkAddress
override def networkAddress: InetSocketAddress = nodeInfo.containerNetworkAddress

def getConfig: Config = config
}
Expand Down
2 changes: 1 addition & 1 deletion node-it/src/test/scala/com/wavesplatform/it/Node.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ abstract class Node(val config: Config) extends AutoCloseable {
)

lazy val grpcChannel: ManagedChannel = ManagedChannelBuilder
.forAddress(networkAddress.getHostString, nodeExternalPort(6870))
.forAddress(nodeApiEndpoint.getHost, nodeExternalPort(6870))
.usePlaintext()
.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class GrpcReflectionApiSuite extends GrpcBaseTransactionSuite {

test("successful getServerReflectionInfo call for BU") {
val buChannel = ManagedChannelBuilder
.forAddress(nodes.head.networkAddress.getHostString, nodes.head.nodeExternalPort(6881))
.forAddress(nodes.head.nodeApiEndpoint.getHost, nodes.head.nodeExternalPort(6881))
.usePlaintext()
.build()
val call = buChannel.newCall(getServerReflectionInfoMethod, CallOptions.DEFAULT)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.wavesplatform.it.sync

import com.typesafe.config.Config
import com.wavesplatform.it.api.SyncHttpApi._
import com.wavesplatform.it.api._
import com.wavesplatform.it.api.*
import com.wavesplatform.it.api.SyncHttpApi.*
import com.wavesplatform.it.{BaseFreeSpec, NodeConfigs}

import scala.concurrent.duration._
import scala.concurrent.duration.*

class BlacklistTestSuite extends BaseFreeSpec {

Expand All @@ -20,7 +20,7 @@ class BlacklistTestSuite extends BaseFreeSpec {
private def otherNodes = dockerNodes().init

"primary node should blacklist other nodes" in {
otherNodes.foreach(n => primaryNode.blacklist(n.containerNetworkAddress))
otherNodes.foreach(n => primaryNode.blacklist(n.networkAddress))

val expectedBlacklistedPeers = nodes.size - 1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.wavesplatform.it.sync.network

import com.typesafe.config.{Config, ConfigFactory}
import com.wavesplatform.it.api.SyncHttpApi._
import com.wavesplatform.it.api.SyncHttpApi.*
import com.wavesplatform.it.{DockerBased, Node, NodeConfigs, Nodes}
import com.wavesplatform.utils.ScorexLogging
import org.scalatest._
import org.scalatest.*

import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.*
import scala.concurrent.duration.*
import scala.util.{Failure, Success, Try}

class NetworkUniqueConnectionsTestSuite extends freespec.AnyFreeSpec with matchers.should.Matchers with DockerBased with ScorexLogging with Nodes {
import NetworkUniqueConnectionsTestSuite._
import NetworkUniqueConnectionsTestSuite.*

"nodes should up and connect with each other" in {
val firstNode = docker.startNode(FirstNodeConfig, autoConnect = false)
Expand All @@ -25,8 +25,8 @@ class NetworkUniqueConnectionsTestSuite extends freespec.AnyFreeSpec with matche
// Helps to do an incoming connection: second -> first (1)
val peersConfig = ConfigFactory.parseString(
s"""waves.network.known-peers = [
| "${firstNode.containerNetworkAddress.getHostName}:${firstNode.containerNetworkAddress.getPort}"
|]""".stripMargin
| "${firstNode.networkAddress.getHostName}:${firstNode.networkAddress.getPort}"
|]""".stripMargin
)

docker.startNode(peersConfig.withFallback(SecondNodeConfig), autoConnect = false)
Expand All @@ -35,7 +35,7 @@ class NetworkUniqueConnectionsTestSuite extends freespec.AnyFreeSpec with matche
firstNode.waitForPeers(1)

// Outgoing connection: first -> second (2)
firstNode.connect(secondNode.containerNetworkAddress)
firstNode.connect(secondNode.networkAddress)

withClue("Should fail with TimeoutException, because the connectionAttempt should fail") {
Try(firstNode.waitForPeers(2, 30.seconds)) match {
Expand Down
2 changes: 1 addition & 1 deletion node/src/main/scala/com/wavesplatform/Explorer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ object Explorer extends ScorexLogging {
case "DA" =>
val addressIds = mutable.Seq[(BigInt, Address)]()
db.iterateOver(KeyTags.AddressId) { e =>
val address = Address.fromBytes(e.getKey.drop(2), settings.blockchainSettings.addressSchemeCharacter.toByte)
val address = Address.fromBytes(e.getKey.drop(2))
val addressId = BigInt(e.getValue)
addressIds :+ (addressId -> address)
}
Expand Down
55 changes: 30 additions & 25 deletions node/src/main/scala/com/wavesplatform/account/Recipient.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.wavesplatform.account

import java.nio.ByteBuffer

import com.google.common.cache.{Cache, CacheBuilder}
import com.google.common.primitives.{Bytes, Ints}
import com.wavesplatform.common.state.ByteStr
Expand All @@ -10,10 +8,12 @@ import com.wavesplatform.crypto
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.lang.v1.traits.domain.Recipient as RideRecipient
import com.wavesplatform.serialization.Deser
import com.wavesplatform.transaction.TxValidationError.{GenericError, InvalidAddress}
import com.wavesplatform.transaction.TxValidationError.{GenericError, InvalidAddress, WrongChain}
import com.wavesplatform.utils.{EthEncoding, StringBytes, base58Length}
import play.api.libs.json.*

import java.nio.ByteBuffer

sealed trait AddressOrAlias {
def chainId: Byte
def bytes: Array[Byte]
Expand Down Expand Up @@ -41,20 +41,19 @@ final case class Alias(chainId: Byte, name: String) extends AddressOrAlias {
object AddressOrAlias {
def fromRide(r: RideRecipient): Either[ValidationError, AddressOrAlias] =
r match {
case RideRecipient.Address(bytes) => Address.fromBytes(bytes.arr)
case RideRecipient.Address(bytes) => Address.fromBytes(bytes.arr, Some(AddressScheme.current.chainId))
case RideRecipient.Alias(name) => Alias.create(name)
}

def fromString(s: String, checkChainId: Boolean = true): Either[ValidationError, AddressOrAlias] = {
def fromString(s: String, expectedChainId: Option[Byte] = None): Either[ValidationError, AddressOrAlias] =
if (s.startsWith(Alias.Prefix))
Alias.fromString(s)
Alias.fromString(s, expectedChainId)
else
Address.fromString(s, if (checkChainId) Some(AddressScheme.current.chainId) else None)
}
Address.fromString(s, expectedChainId)

def fromBytes(buf: Array[Byte]): Either[ValidationError, AddressOrAlias] = buf.headOption match {
case Some(Address.AddressVersion) => Address.fromBytes(buf)
case Some(Alias.AddressVersion) => Alias.fromBytes(buf)
case Some(Address.AddressVersion) => Address.fromBytes(buf, None)
case Some(Alias.AddressVersion) => Alias.fromBytes(buf, None)
case _ => throw new IllegalArgumentException(s"Not a valid recipient: ${ByteStr(buf)}")
}
}
Expand Down Expand Up @@ -111,7 +110,7 @@ object Address {
)
}

def fromBytes(addressBytes: Array[Byte], chainId: Byte = scheme.chainId): Either[InvalidAddress, Address] = {
def fromBytes(addressBytes: Array[Byte], expectedChainId: Option[Byte] = Some(AddressScheme.current.chainId)): Either[InvalidAddress, Address] = {
bytesCache.get(
ByteStr(addressBytes),
{ () =>
Expand All @@ -126,11 +125,11 @@ object Address {

(for {
_ <- Either.cond(version == AddressVersion, (), s"Unknown address version: $version")
_ <- Either.cond(
network == chainId,
(),
s"Address belongs to another network: expected: $chainId(${chainId.toChar}), actual: $network(${network.toChar})"
)
_ <- expectedChainId match {
case Some(exp) if exp != network =>
Left(s"Address belongs to another network: expected: $exp(${exp.toChar}), actual: $network(${network.toChar})")
case _ => Right(())
}
checkSum = addressBytes.takeRight(ChecksumLength)
checkSumGenerated = calcCheckSum(addressBytes.dropRight(ChecksumLength))
_ <- Either.cond(java.util.Arrays.equals(checkSum, checkSumGenerated), (), s"Bad address checksum")
Expand All @@ -140,7 +139,7 @@ object Address {
)
}

def fromString(addressStr: String, chainId: Option[Byte] = Some(scheme.chainId)): Either[ValidationError, Address] = {
def fromString(addressStr: String, expectedChainId: Option[Byte] = Some(AddressScheme.current.chainId)): Either[ValidationError, Address] = {
val base58String = if (addressStr.startsWith(Prefix)) addressStr.drop(Prefix.length) else addressStr
for {
_ <- Either.cond(
Expand All @@ -149,7 +148,7 @@ object Address {
InvalidAddress(s"Wrong address string length: max=$AddressStringLength, actual: ${base58String.length}")
)
byteArray <- Base58.tryDecodeWithLimit(base58String).toEither.left.map(ex => InvalidAddress(s"Unable to decode base58: ${ex.getMessage}"))
address <- fromBytes(byteArray, chainId.getOrElse(byteArray(1)))
address <- fromBytes(byteArray, expectedChainId)
} yield address
}

Expand Down Expand Up @@ -184,7 +183,7 @@ object Alias {
createWithChainId(name, AddressScheme.current.chainId)
}

def fromString(str: String): Either[ValidationError, Alias] = {
def fromString(str: String, expectedChainId: Option[Byte] = Some(AddressScheme.current.chainId)): Either[ValidationError, Alias] = {
val aliasPatternInfo = "Alias string pattern is 'alias:<chain-id>:<address-alias>"

if (!str.startsWith(Prefix)) {
Expand All @@ -196,15 +195,15 @@ object Alias {
if (charSemicolonAlias(1) != ':') {
Left(GenericError(aliasPatternInfo))
} else {
createWithChainId(name, chainId)
createWithChainId(name, chainId, expectedChainId)
}
}
}

def fromBytes(bytes: Array[Byte]): Either[ValidationError, Alias] = {
def fromBytes(bytes: Array[Byte], expectedChainId: Option[Byte]): Either[ValidationError, Alias] = {
bytes match {
case Array(`AddressVersion`, chainId, _, _, rest*) =>
createWithChainId(new String(rest.toArray, "UTF-8"), chainId)
createWithChainId(new String(rest.toArray, "UTF-8"), chainId, expectedChainId)

case _ =>
Left(GenericError("Bad alias bytes"))
Expand All @@ -214,12 +213,18 @@ object Alias {
private[this] def isValidAliasChar(c: Char): Boolean =
('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || c == '_' || c == '@' || c == '-' || c == '.'

private[wavesplatform] def createWithChainId(name: String, chainId: Byte): Either[ValidationError, Alias] = {
private[wavesplatform] def createWithChainId(
name: String,
chainId: Byte,
expectedChainId: Option[Byte] = Some(AddressScheme.current.chainId)
): Either[ValidationError, Alias] =
if (name.length < MinLength || MaxLength < name.length)
Left(GenericError(s"Alias '$name' length should be between $MinLength and $MaxLength"))
else if (!name.forall(isValidAliasChar))
Left(GenericError(s"Alias should contain only following characters: $AliasAlphabet"))
else
Right(new Alias(chainId, name))
}
expectedChainId match {
case Some(expected) if expected != chainId => Left(WrongChain(expected, chainId))
case _ => Right(Alias(chainId, name))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ case class SignedInvokeScriptRequest(
def toTx: Either[ValidationError, InvokeScriptTransaction] =
for {
_sender <- PublicKey.fromBase58String(senderPublicKey)
_dappAddress <- AddressOrAlias.fromString(dApp, checkChainId = false)
_dappAddress <- AddressOrAlias.fromString(dApp)
t <- InvokeScriptTransaction.create(
version.getOrElse(2.toByte),
_sender,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,14 @@ case class UtilsInvocationRequest(
id <- decodeBase58(id)
functionCall = InvokeScriptRequest.buildFunctionCall(call)
feeAssetId <- feeAssetId.traverse(decodeBase58)
sender <-
if (sender.nonEmpty || senderPK == DefaultPublicKey)
sender
.map(Address.fromString(_, None).map(a => RideAddress(ByteStr(a.bytes))))
.getOrElse(Right(RideAddress(ByteStr(new Array[Byte](26)))))
else
Right(RideAddress(ByteStr(senderPK.toAddress.bytes)))
senderAddress <- sender
.fold(RideAddress(ByteStr(senderPK.toAddress.bytes)).asRight[ValidationError]) { s =>
Address.fromString(s).map(a => RideAddress(ByteStr(a.bytes)))
}
payments <- AttachedPaymentExtractor
.extractPayments(payment, V6, blockchainAllowsMultiPayment = true, smart.DApp)
.leftMap(GenericError(_))
} yield Invocation(functionCall, sender, senderPK, sender, senderPK, payments, id, fee, feeAssetId)
} yield Invocation(functionCall, senderAddress, senderPK, senderAddress, senderPK, payments, id, fee, feeAssetId)

private def decodeBase58(base58: String): Either[ValidationError, ByteStr] =
ByteStr.decodeBase58(base58).toEither.leftMap(e => GenericError(String.valueOf(e.getMessage)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with Scor
if (settings.enableBlacklisting) {
unverifiedPeers.synchronized {
unverifiedPeers.removeIf { x =>
Option(x.getAddress).contains(inetAddress.getAddress)
Option(x.getAddress).contains(inetAddress)
}
blacklist.put(inetAddress, System.currentTimeMillis())
reasons.put(inetAddress, reason)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ object PBRecipients {
case Address.HashLength => // Compressed address
val withHeader = Bytes.concat(Array(Address.AddressVersion, chainId), bytes)
val checksum = Address.calcCheckSum(withHeader)
Address.fromBytes(Bytes.concat(withHeader, checksum), chainId)
Address.fromBytes(Bytes.concat(withHeader, checksum), Some(chainId))

case Address.AddressLength => // Regular address
Address.fromBytes(bytes, chainId)
Address.fromBytes(bytes, Some(chainId))

case crypto.KeyLength => // Public key
Right(PublicKey(bytes).toAddress(chainId))
Expand All @@ -36,7 +36,7 @@ object PBRecipients {
}

def toAlias(r: PBRecipient, chainId: Byte): Either[ValidationError, Alias] = r.recipient match {
case PBRecipient.Recipient.Alias(alias) => Alias.createWithChainId(alias, chainId)
case PBRecipient.Recipient.Alias(alias) => Alias.createWithChainId(alias, chainId, Some(chainId))
case _ => Left(GenericError(s"Not an alias: $r"))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,12 @@ object PBTransactions {

case Data.MassTransfer(mt) =>
for {
parsedTransfers <- mt.transfers.flatMap { t =>
t.getRecipient.toAddressOrAlias(chainId).toOption.map { addressOrAlias =>
parsedTransfers <- mt.transfers.traverse { t =>
t.getRecipient.toAddressOrAlias(chainId).flatMap { addressOrAlias =>
TxNonNegativeAmount(t.amount)(NegativeAmount(t.amount, "asset"))
.map(ParsedTransfer(addressOrAlias, _))
}
}.sequence
}
tx <- vt.transfer.MassTransferTransaction.create(
version.toByte,
sender,
Expand Down
Loading

0 comments on commit 7e02801

Please sign in to comment.