Skip to content

Instantly share code, notes, and snippets.

@kushti
Created January 25, 2019 14:23
Show Gist options
  • Save kushti/1e9f6d0add6a5fd926743aaa26d448bd to your computer and use it in GitHub Desktop.
Save kushti/1e9f6d0add6a5fd926743aaa26d448bd to your computer and use it in GitHub Desktop.
package sigmastate.utxo.examples
import java.math.BigInteger
import org.ergoplatform.ErgoBox.{R4, R5, R6}
import org.ergoplatform._
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.utils.Random
import sigmastate.Values.{ByteArrayConstant, ByteConstant, GroupElementConstant, IntConstant, SigmaPropConstant}
import sigmastate._
import sigmastate.basics.DLogProtocol.ProveDlog
import sigmastate.helpers.{ErgoLikeTestProvingInterpreter, SigmaTestingCommons}
import sigmastate.interpreter.CryptoConstants
import sigmastate.interpreter.CryptoConstants.dlogGroup
import sigmastate.interpreter.Interpreter._
import sigmastate.lang.Terms._
import sigmastate.utxo._
class MixExampleSpecification extends SigmaTestingCommons {
implicit lazy val IR = new TestingIRContext
property("Evaluation - Mix Example") {
import CryptoConstants._
// import CryptoConstants.dlogGroup
val gA = dlogGroup.generator
// Alice is first player, who initiates the mix
val alice = new ErgoLikeTestProvingInterpreter
val alicePubKey:ProveDlog = alice.dlogSecrets.head.publicImage
val xA:BigInteger = alice.dlogSecrets.head.w // xA is Alice's private key
// Alternative: can generate xA ourselves
val yA = alicePubKey.value // yA is Alice's public key (yA = gA^xA)
// Alternative: to generate yA ourselves from a BigInteger xA
// val yA:EcPointType = dlogGroup.exponentiate(dlogGroup.generator, xA)
// And to generate yA as ProveDlog type from xA, use the following
// val alicePubKey:ProveDlog = ProveDlog(dlogGroup.exponentiate(dlogGroup.generator, xA))
val fullMixEnv = Map(
ScriptNameProp -> "fullMixEnv",
"gA" -> gA,
"yA" -> yA
)
ProveDlog(yA) shouldBe alicePubKey
val fullMixScript = compileWithCosting(fullMixEnv,
"""{
| val e0 = SELF.R4[GroupElement].get
| val e1 = SELF.R5[GroupElement].get
| proveDlog(e1) || // either last element is of the form gA^xB
| proveDHTuple(gA, yA, e0, e1) // or last element is of the form yA^xB
|}""".stripMargin
).asBoolValue
val halfMixEnv = Map(
ScriptNameProp -> "halfMixEnv",
"gA" -> gA,
"yA" -> alicePubKey.value.asInstanceOf[GroupElementConstant],
"fullMixScriptHash" -> Blake2b256(fullMixScript.bytes)
)
println(halfMixEnv("yA"))
// Note that below script allows Alice to spend the half-mix output anytime before Bob spends it.
// We could also consider a more restricted version of the game where Alice is unable to spend the half-mix output
// before some minimum height.
val halfMixScript = compileWithCosting(halfMixEnv,
"""{
| proveDlog(yA) || {
| val c1 = OUTPUTS(0).R4[GroupElement].get
| val c2 = OUTPUTS(0).R5[GroupElement].get
|
| OUTPUTS.size == 2 &&
| OUTPUTS(0).value == SELF.value &&
| OUTPUTS(1).value == SELF.value &&
| blake2b256(OUTPUTS(0).propositionBytes) == fullMixScriptHash &&
| blake2b256(OUTPUTS(1).propositionBytes) == fullMixScriptHash &&
| OUTPUTS(1).R5[GroupElement].get == c1 &&
| OUTPUTS(1).R4[GroupElement].get == c2 && {
| proveDHTuple(gA, c1, yA, c2) || proveDHTuple(gA, c2, yA, c1)
| }
| }
|}""".stripMargin
).asBoolValue
println(halfMixScript)
/////////////////////////////////////////////////////////
//// Alice starts creating a Half-Mix
/////////////////////////////////////////////////////////
// she creates a transaction that outputs a box with halfGame script.
// In the example, we don't create the transaction; we just create a box below
val halfMixCreationHeight = 70
val mixAmount = 10
val halfMixOutput = ErgoBox(mixAmount, halfMixScript, halfMixCreationHeight)
/////////////////////////////////////////////////////////
//// above halMixOutput is a Half-Mix "box" created by Alice.
/////////////////////////////////////////////////////////
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment