Schnorr sig parsing checks (#4482)

This commit is contained in:
benthecarman 2022-07-10 16:00:38 -05:00 committed by GitHub
parent ec599a5c3d
commit 3821060e68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -20,6 +20,8 @@ import org.bitcoins.core.util.BitcoinScriptUtil
import org.bitcoins.crypto._ import org.bitcoins.crypto._
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scala.util.Try
/** Created by chris on 1/6/16. /** Created by chris on 1/6/16.
*/ */
sealed abstract class CryptoInterpreter { sealed abstract class CryptoInterpreter {
@ -154,33 +156,22 @@ sealed abstract class CryptoInterpreter {
* if the signature is the empty byte vector which trivially * if the signature is the empty byte vector which trivially
* fails script interpreter validation * fails script interpreter validation
*/ */
private def getSignatureAndHashType( private def getSignatureAndHashType(sigBytes: ByteVector): Either[
stack: List[ScriptToken], ScriptError,
isCheckSigAdd: Boolean): Option[(SchnorrDigitalSignature, HashType)] = { (SchnorrDigitalSignature, HashType)] = {
val sigBytes = { val parseT = Try(if (sigBytes.length == 64) {
if (isCheckSigAdd) { val sig = SchnorrDigitalSignature.fromBytes(sigBytes)
stack(2).bytes Right((sig, HashType.sigHashDefault))
} else { } else if (sigBytes.length == 65) {
stack.tail.head.bytes val hashTypeByte = sigBytes.last
} val hashType = HashType.fromByte(hashTypeByte)
} val sig = SchnorrDigitalSignature.fromBytes(sigBytes.dropRight(1))
val sigHashTypeOpt: Option[(SchnorrDigitalSignature, HashType)] = { Right((sig, hashType))
if (sigBytes.length == 64) { } else {
val sig = SchnorrDigitalSignature.fromBytes(sigBytes) Left(ScriptErrorSchnorrSigSize)
Some((sig, HashType.sigHashDefault)) })
} else if (sigBytes.length == 65) {
val hashTypeByte = sigBytes.last parseT.getOrElse(Left(ScriptErrorSchnorrSig))
val hashType = HashType.fromByte(hashTypeByte)
val sig = SchnorrDigitalSignature.fromBytes(sigBytes.dropRight(1))
Some((sig, hashType))
} else if (sigBytes.isEmpty) {
None
} else {
sys.error(
s"Incorrect length for schnorr digital signature, got=${sigBytes.length}, expected 64 or 65 sigBytes=${sigBytes}")
}
}
sigHashTypeOpt
} }
private def evalChecksigTapscript( private def evalChecksigTapscript(
@ -226,19 +217,15 @@ sealed abstract class CryptoInterpreter {
sys.error(s"Invalid pubkey with 32 bytes in size, got=${xOnlyPubKeyT}") sys.error(s"Invalid pubkey with 32 bytes in size, got=${xOnlyPubKeyT}")
} else { } else {
val helperE: Either[ScriptError, TapscriptChecksigHelper] = { val helperE: Either[ScriptError, TapscriptChecksigHelper] = {
val sigHashTypeOpt = getSignatureAndHashType(stack, isCheckSigAdd) val sigHashTypeE = getSignatureAndHashType(sigBytes)
sigHashTypeOpt match { sigHashTypeE.map { case (signature, hashType) =>
case Some((signature, hashType)) => val restOfStack =
val restOfStack = program.stack.tail.tail //remove pubkey, signature
program.stack.tail.tail //remove pubkey, signature val helper = TapscriptChecksigHelper(pubKey = xOnlyPubKeyT.get,
val helper = TapscriptChecksigHelper(pubKey = xOnlyPubKeyT.get, signature = signature,
signature = signature, hashType = hashType,
hashType = hashType, restOfStack = restOfStack)
restOfStack = restOfStack) helper
Right(helper)
case None =>
//this is because the signature was empty
Left(ScriptErrorEvalFalse)
} }
} }
helperE match { helperE match {