mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-26 13:25:49 +01:00
Schnorr sig parsing checks (#4482)
This commit is contained in:
parent
ec599a5c3d
commit
3821060e68
1 changed files with 27 additions and 40 deletions
|
@ -20,6 +20,8 @@ import org.bitcoins.core.util.BitcoinScriptUtil
|
|||
import org.bitcoins.crypto._
|
||||
import scodec.bits.ByteVector
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
/** Created by chris on 1/6/16.
|
||||
*/
|
||||
sealed abstract class CryptoInterpreter {
|
||||
|
@ -154,33 +156,22 @@ sealed abstract class CryptoInterpreter {
|
|||
* if the signature is the empty byte vector which trivially
|
||||
* fails script interpreter validation
|
||||
*/
|
||||
private def getSignatureAndHashType(
|
||||
stack: List[ScriptToken],
|
||||
isCheckSigAdd: Boolean): Option[(SchnorrDigitalSignature, HashType)] = {
|
||||
val sigBytes = {
|
||||
if (isCheckSigAdd) {
|
||||
stack(2).bytes
|
||||
} else {
|
||||
stack.tail.head.bytes
|
||||
}
|
||||
}
|
||||
val sigHashTypeOpt: Option[(SchnorrDigitalSignature, HashType)] = {
|
||||
if (sigBytes.length == 64) {
|
||||
val sig = SchnorrDigitalSignature.fromBytes(sigBytes)
|
||||
Some((sig, HashType.sigHashDefault))
|
||||
} else if (sigBytes.length == 65) {
|
||||
val hashTypeByte = sigBytes.last
|
||||
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 getSignatureAndHashType(sigBytes: ByteVector): Either[
|
||||
ScriptError,
|
||||
(SchnorrDigitalSignature, HashType)] = {
|
||||
val parseT = Try(if (sigBytes.length == 64) {
|
||||
val sig = SchnorrDigitalSignature.fromBytes(sigBytes)
|
||||
Right((sig, HashType.sigHashDefault))
|
||||
} else if (sigBytes.length == 65) {
|
||||
val hashTypeByte = sigBytes.last
|
||||
val hashType = HashType.fromByte(hashTypeByte)
|
||||
val sig = SchnorrDigitalSignature.fromBytes(sigBytes.dropRight(1))
|
||||
Right((sig, hashType))
|
||||
} else {
|
||||
Left(ScriptErrorSchnorrSigSize)
|
||||
})
|
||||
|
||||
parseT.getOrElse(Left(ScriptErrorSchnorrSig))
|
||||
}
|
||||
|
||||
private def evalChecksigTapscript(
|
||||
|
@ -226,19 +217,15 @@ sealed abstract class CryptoInterpreter {
|
|||
sys.error(s"Invalid pubkey with 32 bytes in size, got=${xOnlyPubKeyT}")
|
||||
} else {
|
||||
val helperE: Either[ScriptError, TapscriptChecksigHelper] = {
|
||||
val sigHashTypeOpt = getSignatureAndHashType(stack, isCheckSigAdd)
|
||||
sigHashTypeOpt match {
|
||||
case Some((signature, hashType)) =>
|
||||
val restOfStack =
|
||||
program.stack.tail.tail //remove pubkey, signature
|
||||
val helper = TapscriptChecksigHelper(pubKey = xOnlyPubKeyT.get,
|
||||
signature = signature,
|
||||
hashType = hashType,
|
||||
restOfStack = restOfStack)
|
||||
Right(helper)
|
||||
case None =>
|
||||
//this is because the signature was empty
|
||||
Left(ScriptErrorEvalFalse)
|
||||
val sigHashTypeE = getSignatureAndHashType(sigBytes)
|
||||
sigHashTypeE.map { case (signature, hashType) =>
|
||||
val restOfStack =
|
||||
program.stack.tail.tail //remove pubkey, signature
|
||||
val helper = TapscriptChecksigHelper(pubKey = xOnlyPubKeyT.get,
|
||||
signature = signature,
|
||||
hashType = hashType,
|
||||
restOfStack = restOfStack)
|
||||
helper
|
||||
}
|
||||
}
|
||||
helperE match {
|
||||
|
|
Loading…
Add table
Reference in a new issue