-
Notifications
You must be signed in to change notification settings - Fork 422
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
79b0271
commit f8dc674
Showing
1 changed file
with
101 additions
and
86 deletions.
There are no files selected for viewing
187 changes: 101 additions & 86 deletions
187
grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/GRPCBroadcastSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,99 +1,114 @@ | ||
package com.wavesplatform.api.grpc.test | ||
|
||
import scala.concurrent.{Await, Future} | ||
import scala.concurrent.duration.* | ||
import com.wavesplatform.account.Address | ||
import com.wavesplatform.common.state.ByteStr | ||
import com.wavesplatform.test.{FlatSpec, TestTime} | ||
import com.wavesplatform.transaction.Asset.Waves | ||
import com.wavesplatform.api.common.{CommonTransactionsApi, TransactionMeta} | ||
import com.wavesplatform.api.grpc.TransactionsApiGrpcImpl | ||
import com.wavesplatform.block.Block | ||
import com.wavesplatform.features.BlockchainFeatures | ||
import com.wavesplatform.lang.ValidationError | ||
import com.wavesplatform.common.state.ByteStr | ||
import com.wavesplatform.db.WithDomain | ||
import com.wavesplatform.db.WithState.AddrWithBalance | ||
import com.wavesplatform.history.Domain | ||
import com.wavesplatform.protobuf.transaction.PBTransactions | ||
import com.wavesplatform.state.{Blockchain, Height} | ||
import com.wavesplatform.transaction.{Asset, CreateAliasTransaction, EthTxGenerator, Transaction, TxHelpers, TxVersion} | ||
import com.wavesplatform.transaction.smart.script.trace.TracedResult | ||
import com.wavesplatform.transaction.TransactionType.TransactionType | ||
import com.wavesplatform.utils.{DiffMatchers, EthHelpers} | ||
import io.grpc.StatusException | ||
import monix.execution.Scheduler | ||
import monix.reactive.Observable | ||
import org.scalamock.scalatest.PathMockFactory | ||
import org.scalatest.BeforeAndAfterAll | ||
|
||
class GRPCBroadcastSpec extends FlatSpec with BeforeAndAfterAll with PathMockFactory with EthHelpers with DiffMatchers { | ||
// Fake NTP time | ||
val FakeTime: TestTime = TestTime(100) | ||
import com.wavesplatform.test.{FlatSpec, NumericExt} | ||
import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} | ||
import com.wavesplatform.transaction.assets.exchange.* | ||
import com.wavesplatform.transaction.utils.EthConverters.* | ||
import com.wavesplatform.transaction.{EthTxGenerator, TxExchangeAmount, TxHelpers, TxMatcherFee, TxOrderPrice, TxVersion} | ||
import com.wavesplatform.utils.EthHelpers | ||
import monix.execution.Scheduler.Implicits.global | ||
import org.scalatest.ParallelTestExecution | ||
import org.web3j.crypto.Bip32ECKeyPair | ||
|
||
import scala.concurrent.Await | ||
import scala.concurrent.duration.* | ||
import scala.util.Try | ||
|
||
class GRPCBroadcastSpec extends FlatSpec with EthHelpers with WithDomain with ParallelTestExecution with GrpcApiHelpers { | ||
import GRPCBroadcastSpec.{ethBuyOrderSigned, ethSellOrderSigned} | ||
|
||
"GRPC broadcast" should "accept Exchange with ETH orders" in { | ||
// TODO: [scala3] rewrite | ||
// import com.wavesplatform.transaction.assets.exchange.EthOrderSpec.{ethBuyOrder, ethSellOrder} | ||
|
||
// val blockchain = createBlockchainStub { blockchain => | ||
// val sh = StubHelpers(blockchain) | ||
// sh.creditBalance(ethBuyOrder.senderAddress, *) | ||
// sh.creditBalance(ethSellOrder.senderAddress, *) | ||
// (blockchain.wavesBalances _) | ||
// .when(*) | ||
// .returns( | ||
// Map( | ||
// TxHelpers.defaultAddress -> Long.MaxValue / 3, | ||
// ethBuyOrder.senderAddress -> Long.MaxValue / 3, | ||
// ethSellOrder.senderAddress -> Long.MaxValue / 3 | ||
// ) | ||
// ) | ||
// sh.issueAsset(ByteStr(EthStubBytes32)) | ||
// } | ||
|
||
// val transaction = TxHelpers.exchange(ethBuyOrder, ethSellOrder, price = 100, version = TxVersion.V3, timestamp = 100) | ||
// FakeTime.setTime(transaction.timestamp) | ||
// blockchain.assertBroadcast(transaction) | ||
val assetIssuer = TxHelpers.defaultSigner | ||
val buyerEthAccount = TxHelpers.signer(1).toEthKeyPair | ||
val sellerEthAccount = TxHelpers.signer(2).toEthKeyPair | ||
|
||
val balances = Seq( | ||
AddrWithBalance(buyerEthAccount.toWavesAddress, 1000.waves), | ||
AddrWithBalance(sellerEthAccount.toWavesAddress, 1000.waves), | ||
AddrWithBalance(TxHelpers.matcher.toAddress, 1000.waves) | ||
) | ||
|
||
withDomain(DomainPresets.RideV6, balances) { d => | ||
val grpcApi = getGrpcApi(d) | ||
|
||
// Issue an asset | ||
val issueTx = TxHelpers.issue(assetIssuer, Long.MaxValue) | ||
val testAsset = issueTx.asset | ||
d.appendBlock(issueTx) | ||
|
||
// Transfer asset to seller | ||
d.appendBlock(TxHelpers.transfer(assetIssuer, sellerEthAccount.toWavesAddress, 1000L, testAsset)) | ||
|
||
val ethBuyOrder = ethBuyOrderSigned(testAsset, buyerEthAccount, TxHelpers.timestamp) | ||
val ethSellOrder = ethSellOrderSigned(testAsset, sellerEthAccount, TxHelpers.timestamp) | ||
|
||
val transaction = TxHelpers.exchange(ethBuyOrder, ethSellOrder, TxHelpers.matcher, price = 100, version = TxVersion.V3) | ||
Await.result(grpcApi.broadcast(PBTransactions.protobuf(transaction)), 10.seconds) | ||
} | ||
} | ||
|
||
it should "reject eth transactions" in { | ||
// TODO: [scala3] rewrite | ||
// val blockchain = createBlockchainStub { blockchain => | ||
// val sh = StubHelpers(blockchain) | ||
// sh.creditBalance(TxHelpers.defaultEthAddress, Waves) | ||
// sh.activateFeatures(BlockchainFeatures.BlockV5, BlockchainFeatures.SynchronousCalls) | ||
// } | ||
|
||
// val transaction = EthTxGenerator.generateEthTransfer(TxHelpers.defaultEthSigner, TxHelpers.secondAddress, 10, Waves) | ||
// FakeTime.setTime(transaction.timestamp) | ||
// intercept[Exception](blockchain.assertBroadcast(transaction)).toString should include("ETH transactions should not be broadcasted over gRPC") | ||
} | ||
withDomain(DomainPresets.RideV6) { d => | ||
val grpcApi = getGrpcApi(d) | ||
|
||
val transaction = EthTxGenerator.generateEthTransfer(TxHelpers.defaultEthSigner, TxHelpers.secondAddress, 10, Waves) | ||
|
||
// noinspection NotImplementedCode | ||
implicit class BlockchainBroadcastExt(blockchain: Blockchain) { | ||
def grpcTxApi: TransactionsApiGrpcImpl = | ||
new TransactionsApiGrpcImpl( | ||
blockchain, | ||
new CommonTransactionsApi { | ||
def aliasesOfAddress(address: Address): Observable[(Height, CreateAliasTransaction)] = ??? | ||
def transactionById(txId: ByteStr): Option[TransactionMeta] = ??? | ||
def unconfirmedTransactions: Seq[Transaction] = ??? | ||
def unconfirmedTransactionById(txId: ByteStr): Option[Transaction] = ??? | ||
def calculateFee(tx: Transaction): Either[ValidationError, (Asset, Long, Long)] = ??? | ||
def transactionsByAddress( | ||
subject: Address, | ||
sender: Option[Address], | ||
transactionTypes: Set[TransactionType], | ||
fromId: Option[ByteStr] | ||
): Observable[TransactionMeta] = ??? | ||
def transactionProofs(transactionIds: List[ByteStr]): List[Block.TransactionProof] = ??? | ||
def broadcastTransaction(tx: Transaction): Future[TracedResult[ValidationError, Boolean]] = { | ||
// val differ = blockchain.stub.transactionDiffer(FakeTime) | ||
// Future.successful(differ(tx).map(_ => true)) | ||
??? | ||
} | ||
} | ||
)(Scheduler.global) | ||
|
||
@throws[StatusException]("on failed broadcast") | ||
def assertBroadcast(tx: Transaction): Unit = { | ||
Await.result(grpcTxApi.broadcast(PBTransactions.protobuf(tx)), 10.seconds) | ||
Try(Await.result(grpcApi.broadcast(PBTransactions.protobuf(transaction)), 10.seconds)).toEither should matchPattern { | ||
case Left(err) if err.toString.contains("ETH transactions should not be broadcasted over gRPC") => | ||
} | ||
} | ||
} | ||
|
||
private def getGrpcApi(d: Domain) = | ||
new TransactionsApiGrpcImpl(d.blockchain, d.transactionsApi) | ||
} | ||
|
||
object GRPCBroadcastSpec extends EthHelpers { | ||
private val emptySignature = OrderAuthentication.Eip712Signature(ByteStr(new Array[Byte](64))) | ||
|
||
def ethBuyOrderSigned(testAsset: IssuedAsset, buyerEthAccount: Bip32ECKeyPair, timestamp: Long): Order = { | ||
val ethBuyOrderTemplate: Order = Order( | ||
Order.V4, | ||
emptySignature, | ||
TxHelpers.matcher.publicKey, | ||
AssetPair(testAsset, Waves), | ||
OrderType.BUY, | ||
TxExchangeAmount.unsafeFrom(1), | ||
TxOrderPrice.unsafeFrom(100L), | ||
timestamp, | ||
timestamp + 10000, | ||
TxMatcherFee.unsafeFrom(100000), | ||
Waves | ||
) | ||
|
||
ethBuyOrderTemplate.copy( | ||
orderAuthentication = OrderAuthentication.Eip712Signature(ByteStr(EthOrders.signOrder(ethBuyOrderTemplate, buyerEthAccount))) | ||
) | ||
} | ||
|
||
def ethSellOrderSigned(testAsset: IssuedAsset, sellerEthAccount: Bip32ECKeyPair, timestamp: Long): Order = { | ||
val ethSellOrderTemplate: Order = Order( | ||
Order.V4, | ||
emptySignature, | ||
TxHelpers.matcher.publicKey, | ||
AssetPair(testAsset, Waves), | ||
OrderType.SELL, | ||
TxExchangeAmount.unsafeFrom(1), | ||
TxOrderPrice.unsafeFrom(100L), | ||
timestamp, | ||
timestamp + 10000, | ||
TxMatcherFee.unsafeFrom(100000), | ||
Waves | ||
) | ||
|
||
ethSellOrderTemplate.copy( | ||
orderAuthentication = OrderAuthentication.Eip712Signature(ByteStr(EthOrders.signOrder(ethSellOrderTemplate, sellerEthAccount))) | ||
) | ||
} | ||
} |