Skip to content

Commit

Permalink
multisig: execute CreateSignature action (v1)
Browse files Browse the repository at this point in the history
  • Loading branch information
aslesarenko committed Aug 1, 2023
1 parent 9923e18 commit 2846140
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ trait ProverUtils extends Interpreter {
realSecretsToExtract: Seq[SigmaBoolean],
simulatedSecretsToExtract: Seq[SigmaBoolean] = Seq.empty): HintsBag = {
val reduced = fullReduction(ergoTree, context, Interpreter.emptyEnv)
bagForMultisig(context, reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract)
bagForMultisig(reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract)
}

/**
Expand All @@ -89,15 +89,13 @@ trait ProverUtils extends Interpreter {
*
* See DistributedSigSpecification for examples of usage.
*
* @param context - context used to reduce the proposition
* @param sigmaTree - public key (in form of a sigma-tree)
* @param proof - signature for the key
* @param realSecretsToExtract - public keys of secrets with real proofs
* @param simulatedSecretsToExtract - public keys of secrets with simulated proofs
* @return - bag of OtherSecretProven and OtherCommitment hints
*/
def bagForMultisig(context: CTX,
sigmaTree: SigmaBoolean,
def bagForMultisig(sigmaTree: SigmaBoolean,
proof: Array[Byte],
realSecretsToExtract: Seq[SigmaBoolean],
simulatedSecretsToExtract: Seq[SigmaBoolean]): HintsBag = {
Expand Down
16 changes: 16 additions & 0 deletions sdk/shared/src/main/scala/org/ergoplatform/sdk/SigmaProver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.ergoplatform.sdk
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
import org.ergoplatform._
import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext
import sigmastate.SigmaLeaf
import sigmastate.Values.SigmaBoolean
import sigmastate.eval.{CostingSigmaDslBuilder, SigmaDsl}
import sigmastate.interpreter.HintsBag
Expand Down Expand Up @@ -91,6 +92,21 @@ class SigmaProver(private[sdk] val _prover: AppkitProvingInterpreter, networkPre
_prover.generateCommitments(sigmaTree)
}

def extractHints(
proposition: SigmaBoolean,
proof: Array[Byte],
realSecretsToExtract: Seq[SigmaLeaf],
simulatedSecretsToExtract: Seq[SigmaLeaf]): HintsBag = {
_prover.bagForMultisig(proposition, proof, realSecretsToExtract, simulatedSecretsToExtract)
}

def generateProof(
sb: SigmaBoolean,
messageToSign: Array[Byte],
hintsBag: HintsBag): Array[Byte] = {
_prover.generateProof(sb, messageToSign, hintsBag)
}

override def equals(obj: Any): Boolean = obj match {
case that: SigmaProver =>
if (!this.hasSecrets || !that.hasSecrets) this eq that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ case class ReducedTransaction(ergoTx: ReducedErgoLikeTransaction) {
* The proofs can be generated by a single prover or by a group of co-singing provers.
*/
lazy val inputPropositions: Seq[SigmaBoolean] = ergoTx.reducedInputs.map(_.reductionResult.value)

/** @return transaction bytes to be signed by a prover (so called "message to sign"). */
def bytesToSign: Array[Byte] = ergoTx.unsignedTx.messageToSign
}

/** Represents results for transaction signing by a prover like [[SigmaProver]]. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.ergoplatform.sdk.multisig

import sigmastate.SigmaLeaf

import scala.collection.mutable

class CosigningServer {
Expand All @@ -15,11 +17,11 @@ class CosigningServer {
sessions.get(id)
}

def getSessionsFor(signer: Signer): Seq[SigningSession] = {
val signerKeys = signer.allKeys.toSet
def getSessionsFor(signerKeys: Seq[SigmaLeaf]): Seq[SigningSession] = {
val keyset = signerKeys.toSet
sessions.values.filter { s =>
s.positionsToProve.exists { positionedLeafs =>
positionedLeafs.exists(pl => signerKeys.contains(pl.leaf))
positionedLeafs.exists(pl => keyset.contains(pl.leaf))
}
}.toSeq
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Signer(val prover: SigmaProver) {
/** Mapping from (session id, input proposition) stored hints. */
private val sessions = mutable.HashMap.empty[(SessionId, SigmaBoolean), HintsBag]

/** Mapping from (session id, input proposition) stored proof hints. */
private val proofs = mutable.HashMap.empty[(SessionId, SigmaBoolean), HintsBag]

def masterAddress: P2PKAddress = prover.getP2PKAddress

def pubkey: SigmaLeaf = masterAddress.pubkey
Expand All @@ -43,6 +46,13 @@ class Signer(val prover: SigmaProver) {
bag.realCommitments
}

private def generateProof(
sb: SigmaBoolean, sessionId: SessionId,
messageToSign: Array[Byte],
hintsBag: HintsBag): Array[Byte] = {
prover.generateProof(sb, messageToSign, hintsBag)
}

def getActionsFrom(session: SigningSession): Seq[SigningAction] = {
val canProveInputs = session.positionsToProve.map { positions =>
positions.filter { pl => canProve(pl.leaf) }
Expand All @@ -59,24 +69,22 @@ class Signer(val prover: SigmaProver) {
}

def execute(action: SigningAction, session: SigningSession): SigningSession = {
val proposition = session.reduced.inputPropositions(action.inputIndex)
val newHints = action match {
case CreateCommitment(_, inputIndex, pl) =>
val proposition = session.reduced.inputPropositions(inputIndex)
val commitments = generateCommitments(proposition, session.id)
commitments.filter { c => c.position == pl.position && c.image == pl.leaf }

// case CreateSignature(signer) =>
// val positions = positionsToProve
// val signatures = positions.map { positions =>
// positions.map { pl =>
// val leaf = pl.leaf
// val position = pl.position
// val signature = signer.prover.createSignature(leaf, position, collectedHints)
// (leaf, position, signature)
// }
// }
// collectedHints.addHints(signatures)
case _ => Seq.empty
commitments.filter(c => c.position == pl.position && c.image == pl.leaf)

case CreateSignature(_, inputIndex, pl) =>
val ownCommitments = getHintsBag(session.id, proposition).get.ownCommitments
val otherCommitments = session.collectedHints(inputIndex)
.filter(_.image != pl.leaf)
val proof = generateProof(proposition,
session.id,
session.reduced.bytesToSign,
otherCommitments.addHints(ownCommitments: _*))
val proofHints = prover.extractHints(proposition, proof, Seq(pl.leaf), Seq.empty)
proofHints.realProofs.filter(rp => rp.position == pl.position && rp.image == pl.leaf)
}
session.addHintsAt(action.inputIndex, newHints)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class SigningSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matcher
val signerPk = signer.pubkey

// participants can retrieve related sessions
val session = server.getSessionsFor(signer).head
val session = server.getSessionsFor(signer.allKeys).head
session.reduced shouldBe reduced

// obtain next actions for the current session state
Expand All @@ -152,6 +152,19 @@ class SigningSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matcher
server.getSession(sessionId).get.collectedHints.size shouldBe cosigners.size


// each cosigner generated a commitment and stores it in the session
cosigners.zipWithIndex.foreach { case (signer, i) =>
val signerPk = signer.pubkey
val session = server.getSessionsFor(signer.allKeys).head
val actions = signer.getActionsFrom(session)

val expectedAction = CreateSignature(signerPk, i, PositionedLeaf.at()(signerPk))
actions shouldBe Seq(expectedAction)
val newSession = signer.execute(actions.head, session)

server.updateSession(newSession)
}

}
}

Expand Down

0 comments on commit 2846140

Please sign in to comment.