Skip to content

Commit

Permalink
Merge pull request #919 from ScorexFoundation/new-p2sh
Browse files Browse the repository at this point in the history
P2SH address to use 126 as scriptId
  • Loading branch information
aslesarenko authored Sep 26, 2023
2 parents f9c067d + 36ca6c9 commit bf81ea9
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package org.ergoplatform

import scorex.utils.Ints
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
import scorex.crypto.hash.{Digest32, Blake2b256}
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.util.encode.Base58
import sigmastate.Values._
import sigmastate._
import sigmastate.crypto.DLogProtocol.{ProveDlogProp, ProveDlog}
import sigmastate.crypto.DLogProtocol.{ProveDlog, ProveDlogProp}
import sigmastate.exceptions.SigmaException
import sigmastate.serialization._
import sigmastate.utxo.{DeserializeContext, Slice}
Expand Down Expand Up @@ -128,7 +128,9 @@ object P2PKAddress {
}
}

/** Implementation of pay-to-script-hash [[ErgoAddress]]. */
/** Implementation of pay-to-script-hash [[ErgoAddress]].
* @param scriptHash first 192 bits of the Blake2b256 hash of serialized script bytes
*/
class Pay2SHAddress(val scriptHash: Array[Byte])(implicit val encoder: ErgoAddressEncoder) extends ErgoAddress {
override val addressTypePrefix: Byte = Pay2SHAddress.addressTypePrefix

Expand All @@ -141,12 +143,12 @@ class Pay2SHAddress(val scriptHash: Array[Byte])(implicit val encoder: ErgoAddre
/** The proposition which checks that `contextVar(scriptId)` has original script
* (whose hash equals to this [[scriptHash]]) which evaluates to true.
*
* Assumes the context variable is accessed as `getVar[Coll[Byte]](1).get`
* Assumes the context variable is accessed as `getVar[Coll[Byte]](126).get`
* and contains serialized original script bytes.
*
* NOTE: This script is not stored in [[contentBytes]] of the address.
* NOTE: This `script` field is not stored in [[contentBytes]] of the address.
* So the address doesn't depend on this script which means this specific script can be
* changed without breaking the addresses.
* changed without breaking the existing p2sh addresses.
*
* NOTE: The ErgoTree is created without segregation of the constants.
*
Expand All @@ -158,7 +160,7 @@ class Pay2SHAddress(val scriptHash: Array[Byte])(implicit val encoder: ErgoAddre
override val script = {
val hashEquals = EQ(
Slice(CalcBlake2b256(GetVarByteArray(scriptId).get), IntConstant(0), IntConstant(24)),
scriptHash
ByteArrayConstant(scriptHash)
)
val scriptIsCorrect = DeserializeContext(scriptId, SSigmaProp)
ErgoTree.withoutSegregation(SigmaAnd(hashEquals.toSigmaProp, scriptIsCorrect))
Expand All @@ -176,9 +178,10 @@ class Pay2SHAddress(val scriptHash: Array[Byte])(implicit val encoder: ErgoAddre

object Pay2SHAddress {
/** An id of the context variable used in pay-to-script-hash address script.
* Note, value 127 is used for strage rent in Ergo node, see org.ergoplatform.wallet.interpreter.ErgoInterpreter
* @see [[Pay2SHAddress.script]]
*/
val scriptId = 1: Byte
val scriptId = 126: Byte

/** Value added to the prefix byte in the serialized bytes of an encoded P2SH address.
* @see [[ErgoAddressEncoder.toString]]
Expand Down Expand Up @@ -300,7 +303,7 @@ case class ErgoAddressEncoder(networkPrefix: NetworkPrefix) {
new P2PKAddress(ProveDlog(p), contentBytes)
case Pay2SHAddress.addressTypePrefix =>
if (contentBytes.length != 24) { //192-bits hash used
throw new Exception(s"Improper content in P2SH script: $addrBase58Str")
throw new Exception(s"Invalid length of the hash bytes in P2SH address: $addrBase58Str")
}
new Pay2SHAddress(contentBytes)
case Pay2SAddress.addressTypePrefix =>
Expand Down Expand Up @@ -328,7 +331,8 @@ case class ErgoAddressEncoder(networkPrefix: NetworkPrefix) {
}

/** Converts the given [[ErgoTree]] to the corresponding [[ErgoAddress]].
* It is inverse of [[ErgoAddress.script]] such that `fromProposition(addr.script) == addr`
* It is inverse of [[ErgoAddress.script]] such that
* `ErgoAddressEncoder.fromProposition(addr.script) == addr`
*
* @return Failure(ex) if the `proposition` cannot be converted to any type of address.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class ErgoAddressSpecification extends SigmaDslTesting

assertExceptionThrown(
ergoAddressEncoder.fromString(addrStr).getOrThrow,
t => t.getMessage.contains("Improper content in P2SH script: 41fKjb7zWNw")
t => t.getMessage.contains("Invalid length of the hash bytes in P2SH address: 41fKjb7zWNw")
)
}

Expand Down Expand Up @@ -228,7 +228,7 @@ class ErgoAddressSpecification extends SigmaDslTesting
}

def testPay2SHAddress(address: Pay2SHAddress, scriptBytes: Array[Byte]) = {
val scriptId = 1.toByte
val scriptId = Pay2SHAddress.scriptId
val boxToSpend = testBox(10, address.script, creationHeight = 5)
val ctx = ErgoLikeContextTesting.dummy(boxToSpend, activatedVersionInTests)
.withExtension(ContextExtension(Seq(
Expand Down Expand Up @@ -271,7 +271,7 @@ class ErgoAddressSpecification extends SigmaDslTesting
res
}

val scriptVarId = 1.toByte
val scriptVarId = Pay2SHAddress.scriptId
val script = "{ 1 < 2 }"
val prop = compile(Map.empty, script).asBoolValue.toSigmaProp
val scriptBytes = ValueSerializer.serialize(prop)
Expand Down

0 comments on commit bf81ea9

Please sign in to comment.