From 4ec1b49712d291d6e96eb1bb4c1344da7e2e3666 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 17 Aug 2023 23:11:14 +0200 Subject: [PATCH] tx-signing-js: ReducedTransaction exported to JS and can be serialised and deserialized --- .../scala/sigmastate/eval/Extensions.scala | 3 ++ .../ergoplatform/sdk/js/ProverBuilder.scala | 11 ++++++-- .../sdk/js/ReducedTransaction.scala | 20 +++++++++++++ .../org/ergoplatform/sdk/js/SigmaProver.scala | 28 +++++++++++++------ .../org/ergoplatform/sdk/ProverBuilder.scala | 8 +++++- .../org/ergoplatform/sdk/Transactions.scala | 21 +++++++++++++- 6 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala b/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala index d765e01c41..b4efc58348 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala @@ -4,6 +4,7 @@ import debox.{cfor, Buffer => DBuffer} import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.TokenId import scalan.{Nullable, RType} +import scorex.util.encode.Base16 import sigmastate.SType.AnyOps import sigmastate.Values.{Constant, ConstantNode} import sigmastate.crypto.{CryptoFacade, Ecp} @@ -41,6 +42,8 @@ object Extensions { implicit class ArrayByteOps(val arr: Array[Byte]) extends AnyVal { /** Wraps array into TokenId instance. The source array in not cloned. */ @inline def toTokenId: TokenId = Digest32Coll @@ Colls.fromArray(arr) + /** Encodes array into hex string */ + @inline def toHex: String = Base16.encode(arr) } implicit class EvalIterableOps[T: RType](seq: Iterable[T]) { diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala index ffbc0e1a41..2660093165 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala @@ -1,6 +1,5 @@ package org.ergoplatform.sdk.js -import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import org.ergoplatform.sdk import org.ergoplatform.sdk.SecretString @@ -9,9 +8,15 @@ import scala.scalajs.js.annotation.JSExportTopLevel import Isos._ import sigmastate.eval.SigmaDsl -/** Equivalent of [[sdk.ProverBuilder]] available from JS. */ +/** Equivalent of [[sdk.ProverBuilder]] available from JS. + * + * @param parameters Blockchain parameters re-adjustable via miners voting and + * voting-related data. All of them are included into extension + * section of a first block of a voting epoch. + * @param network Network prefix to use for addresses. + */ @JSExportTopLevel("ProverBuilder") -class ProverBuilder(parameters: BlockchainParameters, network: NetworkPrefix) extends js.Object { +class ProverBuilder(parameters: BlockchainParameters, network: Byte) extends js.Object { val _builder = new sdk.ProverBuilder(parameters, network) /** Configure this builder to use the given seed when building a new prover. diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala new file mode 100644 index 0000000000..30c63f5c33 --- /dev/null +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala @@ -0,0 +1,20 @@ +package org.ergoplatform.sdk.js + +import org.ergoplatform.sdk +import scala.scalajs.js.annotation.JSExportTopLevel + +/** Equivalent of [[sdk.ReducedTransaction]] available from JS. */ +@JSExportTopLevel("ReducedTransaction") +class ReducedTransaction(private[js] val _tx: sdk.ReducedTransaction) { + /** Serialized bytes of this transaction in hex format. */ + def toHex: String = _tx.toHex +} + +@JSExportTopLevel("ReducedTransactionObj") +object ReducedTransaction { + /** Creates a [[ReducedTransaction]] from serialized bytes in hex format. */ + def fromHex(hex: String): ReducedTransaction = { + val tx = sdk.ReducedTransaction.fromHex(hex) + new ReducedTransaction(tx) + } +} \ No newline at end of file diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala index 621fae4208..b7ca33b1de 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala @@ -13,6 +13,25 @@ import scala.scalajs.js.annotation.JSExportTopLevel class SigmaProver(_prover: sdk.SigmaProver) extends js.Object { import Isos._ + /** Returns the Pay-to-Public-Key (P2PK) address associated with the prover's public key. + * The returned address corresponds to the master secret derived from the mnemonic + * phrase configured in the [[ProverBuilder]]. + */ + def getP2PKAddress: String = { + val addr = _prover.getP2PKAddress + addr.toString + } + + /** Returns the prover's secret key. */ + def getSecretKey: js.BigInt = + isoBigInt.from(_prover.getSecretKey) + + /** Returns a sequence of EIP-3 addresses associated with the prover's secret keys. */ + def getEip3Addresses: js.Array[String] = { + val addresses = _prover.getEip3Addresses + js.Array(addresses.map(_.toString): _*) + } + /** Reduces the transaction to the reduced form, which is ready to be signed. * @param stateCtx blockchain state context * @param unsignedTx unsigned transaction to be reduced (created by Fleet builders) @@ -49,12 +68,3 @@ class SigmaProver(_prover: sdk.SigmaProver) extends js.Object { isoSignedTransaction.from(signed.ergoTx) } } - -//TODO finish implementation -@JSExportTopLevel("ReducedTransaction") -class ReducedTransaction(private [js] val _tx: sdk.ReducedTransaction) - -//TODO finish implementation -@JSExportTopLevel("SigmaProverObj") -object SigmaProver { -} diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ProverBuilder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ProverBuilder.scala index 1e13962e18..0704cbe8d6 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ProverBuilder.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ProverBuilder.scala @@ -9,7 +9,13 @@ import special.sigma.GroupElement import java.math.BigInteger import scala.collection.mutable.ArrayBuffer -/** A builder class for constructing a `Prover` with specified secrets. */ +/** A builder class for constructing a `Prover` with specified secrets. + * + * @param parameters Blockchain parameters re-adjustable via miners voting and + * voting-related data. All of them are included into extension + * section of a first block of a voting epoch. + * @param networkPrefix Network prefix to use for addresses. + */ class ProverBuilder(parameters: BlockchainParameters, networkPrefix: NetworkPrefix) { private var _masterKey: Option[ExtendedSecretKey] = None diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala index 8073b77c9e..275814a983 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala @@ -1,6 +1,9 @@ package org.ergoplatform.sdk +import org.ergoplatform.sdk.JavaHelpers.StringExtensions import org.ergoplatform.{ErgoBox, ErgoLikeTransaction, UnsignedErgoLikeTransaction} +import sigmastate.eval.Extensions.ArrayByteOps +import sigmastate.serialization.SigmaSerializer import java.util @@ -45,7 +48,23 @@ case class UnreducedTransaction( } /** Represents results for transaction reduction by [[ReducingInterpreter]]. */ -case class ReducedTransaction(ergoTx: ReducedErgoLikeTransaction) +case class ReducedTransaction(ergoTx: ReducedErgoLikeTransaction) { + /** Serialized bytes of this transaction in hex format. */ + def toHex: String = { + val w = SigmaSerializer.startWriter() + ReducedErgoLikeTransactionSerializer.serialize(ergoTx, w) + w.toBytes.toHex + } +} + +object ReducedTransaction { + /** Creates a [[ReducedTransaction]] from serialized bytes in hex format. */ + def fromHex(hex: String): ReducedTransaction = { + val r = SigmaSerializer.startReader(hex.toBytes) + val tx = ReducedErgoLikeTransactionSerializer.parse(r) + ReducedTransaction(tx) + } +} /** Represents results for transaction signing by a prover like [[SigmaProver]]. */ case class SignedTransaction(ergoTx: ErgoLikeTransaction, cost: Int)