com.wavesplatform.state.diffs.EthereumTransactionDiff.scala Maven / Gradle / Ivy
The newest version!
package com.wavesplatform.state.diffs
import cats.implicits.catsSyntaxSemigroup
import com.google.protobuf.ByteString
import com.wavesplatform.crypto.EthereumKeyLength
import com.wavesplatform.database.protobuf.EthereumTransactionMeta
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.lang.v1.serialization.SerdeV1
import com.wavesplatform.protobuf.transaction.{PBAmounts, PBRecipients}
import com.wavesplatform.state.diffs.invoke.{InvokeDiffsCommon, InvokeScriptTransactionDiff}
import com.wavesplatform.state.{Blockchain, StateSnapshot}
import com.wavesplatform.transaction.EthereumTransaction
import com.wavesplatform.transaction.TxValidationError.GenericError
import com.wavesplatform.transaction.smart.script.trace.TracedResult
object EthereumTransactionDiff {
def meta(blockchain: Blockchain)(tx: EthereumTransaction): StateSnapshot = {
val resultEi = tx.payload match {
case et: EthereumTransaction.Transfer =>
for {
_ <- et.checkTransferDataSize(blockchain, tx.underlying.getData)
assetId <- et.tryResolveAsset(blockchain)
} yield StateSnapshot(
ethereumTransactionMeta = Map(
tx.id() -> EthereumTransactionMeta(
EthereumTransactionMeta.Payload.Transfer(
EthereumTransactionMeta.Transfer(
ByteString.copyFrom(PBRecipients.publicKeyHash(et.recipient)),
Some(PBAmounts.fromAssetAndAmount(assetId, et.amount))
)
)
)
)
)
case ei: EthereumTransaction.Invocation =>
for {
invocation <- ei.toInvokeScriptLike(tx, blockchain)
} yield StateSnapshot(
ethereumTransactionMeta = Map(
tx.id() -> EthereumTransactionMeta(
EthereumTransactionMeta.Payload.Invocation(
EthereumTransactionMeta.Invocation(
ByteString.copyFrom(SerdeV1.serialize(invocation.funcCall)),
invocation.payments.map(p => PBAmounts.fromAssetAndAmount(p.assetId, p.amount))
)
)
)
)
)
}
resultEi.getOrElse(StateSnapshot.empty)
}
def apply(blockchain: Blockchain, currentBlockTs: Long, limitedExecution: Boolean, enableExecutionLog: Boolean)(
tx: EthereumTransaction
): TracedResult[ValidationError, StateSnapshot] = {
val baseDiff = tx.payload match {
case et: EthereumTransaction.Transfer =>
for {
_ <- checkLeadingZeros(tx, blockchain)
_ <- TracedResult(et.checkTransferDataSize(blockchain, tx.underlying.getData))
asset <- TracedResult(et.tryResolveAsset(blockchain))
transfer <- TracedResult(et.toTransferLike(tx, blockchain))
assetSnapshot <- TransactionDiffer.assetsVerifierDiff(
blockchain,
transfer,
verify = true,
StateSnapshot(),
Int.MaxValue,
enableExecutionLog
)
snapshot <- TransferDiff(blockchain)(tx.senderAddress(), et.recipient, et.amount, asset, tx.fee, tx.feeAssetId)
} yield assetSnapshot |+| snapshot
case ei: EthereumTransaction.Invocation =>
for {
_ <- checkLeadingZeros(tx, blockchain)
invocation <- TracedResult(ei.toInvokeScriptLike(tx, blockchain))
_ <- TracedResult(InvokeDiffsCommon.checkPayments(blockchain, invocation.payments))
snapshot <- InvokeScriptTransactionDiff(blockchain, currentBlockTs, limitedExecution, enableExecutionLog)(invocation)
resultSnapshot <- TransactionDiffer.assetsVerifierDiff(
blockchain,
invocation,
verify = true,
snapshot,
Int.MaxValue,
enableExecutionLog
)
} yield snapshot.copy(scriptsComplexity = resultSnapshot.scriptsComplexity)
}
baseDiff.map(_ |+| meta(blockchain)(tx))
}
private def checkLeadingZeros(tx: EthereumTransaction, blockchain: Blockchain): TracedResult[ValidationError, Unit] = {
TracedResult(
Either.cond(
!(tx.signerKeyBigInt().toByteArray.length < EthereumKeyLength) || blockchain.isFeatureActivated(BlockchainFeatures.ConsensusImprovements),
(),
GenericError("Invalid public key")
)
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy