mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-26 21:42:48 +01:00
Rework WitnessVersion.rebuild() to take WitnessScriptPubKey as a parameter (#4393)
* Rework WitnessVersion.rebuild() to take WitnessScriptPubKey as a parameter rather than the raw asm * Fix bug when calculating witness program length * Fix witnessProgram bug in ScriptInterpreter.rebuildV0() * remove invariant, fix type
This commit is contained in:
parent
ad8802164c
commit
acd1d227cf
3 changed files with 23 additions and 17 deletions
|
@ -20,7 +20,7 @@ sealed trait WitnessVersion {
|
|||
*/
|
||||
def rebuild(
|
||||
scriptWitness: ScriptWitness,
|
||||
witnessProgram: Seq[ScriptToken]): Either[ScriptError, ScriptPubKey]
|
||||
witnessSPK: WitnessScriptPubKey): Either[ScriptError, ScriptPubKey]
|
||||
|
||||
def version: ScriptNumberOperation
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ case object WitnessVersion0 extends WitnessVersion {
|
|||
/** Rebuilds a witness version 0 SPK program, see BIP141 */
|
||||
override def rebuild(
|
||||
scriptWitness: ScriptWitness,
|
||||
witnessProgram: Seq[ScriptToken]): Either[ScriptError, ScriptPubKey] = {
|
||||
witnessSPK: WitnessScriptPubKey): Either[ScriptError, ScriptPubKey] = {
|
||||
val witnessProgram = witnessSPK.witnessProgram
|
||||
val programBytes = BytesUtil.toByteVector(witnessProgram)
|
||||
programBytes.size match {
|
||||
case 20 =>
|
||||
|
@ -68,8 +69,9 @@ case object WitnessVersion1 extends WitnessVersion {
|
|||
|
||||
override def rebuild(
|
||||
scriptWitness: ScriptWitness,
|
||||
witnessProgram: Seq[ScriptToken]): Either[ScriptError, ScriptPubKey] = {
|
||||
throw new UnsupportedOperationException("Taproot is not yet supported")
|
||||
witnessSPK: WitnessScriptPubKey): Either[ScriptError, ScriptPubKey] = {
|
||||
throw new UnsupportedOperationException(
|
||||
s"Taproot is not yet supported $scriptWitness $witnessSPK")
|
||||
}
|
||||
|
||||
override def version: ScriptNumberOperation = OP_1
|
||||
|
@ -85,8 +87,9 @@ case class UnassignedWitness(version: ScriptNumberOperation)
|
|||
|
||||
override def rebuild(
|
||||
scriptWitness: ScriptWitness,
|
||||
witnessProgram: Seq[ScriptToken]): Either[ScriptError, ScriptPubKey] =
|
||||
witnessSPK: WitnessScriptPubKey): Either[ScriptError, ScriptPubKey] = {
|
||||
Left(ScriptErrorDiscourageUpgradeableWitnessProgram)
|
||||
}
|
||||
}
|
||||
|
||||
object WitnessVersion {
|
||||
|
|
|
@ -335,9 +335,7 @@ sealed abstract class ScriptInterpreter {
|
|||
case w: WitnessTxSigComponent =>
|
||||
val scriptSig =
|
||||
scriptPubKeyExecutedProgram.txSignatureComponent.scriptSignature
|
||||
val (witnessVersion, witnessProgram) =
|
||||
(witnessScriptPubKey.witnessVersion,
|
||||
witnessScriptPubKey.witnessProgram)
|
||||
val witnessVersion = witnessScriptPubKey.witnessVersion
|
||||
val witness = w.witness
|
||||
//scriptsig must be empty if we have raw p2wsh
|
||||
//if script pubkey is a P2SHScriptPubKey then we have P2SH(P2WSH)
|
||||
|
@ -348,7 +346,10 @@ sealed abstract class ScriptInterpreter {
|
|||
scriptPubKeyExecutedProgram.failExecution(ScriptErrorPushSize)
|
||||
)
|
||||
} else {
|
||||
verifyWitnessProgram(witnessVersion, witness, witnessProgram, w)
|
||||
verifyWitnessProgram(witnessVersion,
|
||||
witness,
|
||||
witnessScriptPubKey,
|
||||
w)
|
||||
}
|
||||
case (_, _) =>
|
||||
Success(
|
||||
|
@ -389,7 +390,7 @@ sealed abstract class ScriptInterpreter {
|
|||
private def verifyWitnessProgram(
|
||||
witnessVersion: WitnessVersion,
|
||||
scriptWitness: ScriptWitness,
|
||||
witnessProgram: Seq[ScriptToken],
|
||||
witnessSPK: WitnessScriptPubKey,
|
||||
wTxSigComponent: WitnessTxSigComponent): Try[ExecutedScriptProgram] = {
|
||||
|
||||
/** Helper function to run the post segwit execution checks */
|
||||
|
@ -405,9 +406,12 @@ sealed abstract class ScriptInterpreter {
|
|||
else evaluated
|
||||
}
|
||||
|
||||
def rebuildV0(witness: ScriptWitness, program: Seq[ScriptToken]): Either[
|
||||
def rebuildV0(
|
||||
witness: ScriptWitness,
|
||||
witnessSPKV0: WitnessScriptPubKey): Either[
|
||||
ScriptError,
|
||||
(Seq[ScriptToken], ScriptPubKey)] = {
|
||||
val program = witnessSPKV0.witnessProgram
|
||||
val programBytes = BytesUtil.toByteVector(program)
|
||||
programBytes.size match {
|
||||
case 20 =>
|
||||
|
@ -416,7 +420,7 @@ sealed abstract class ScriptInterpreter {
|
|||
Left(ScriptErrorWitnessProgramMisMatch)
|
||||
} else {
|
||||
for {
|
||||
rebuilt <- WitnessVersion0.rebuild(witness, program)
|
||||
rebuilt <- WitnessVersion0.rebuild(witness, witnessSPKV0)
|
||||
r <- Right((witness.stack.map(ScriptConstant(_)), rebuilt))
|
||||
} yield r
|
||||
}
|
||||
|
@ -425,7 +429,7 @@ sealed abstract class ScriptInterpreter {
|
|||
if (scriptWitness.stack.isEmpty)
|
||||
Left(ScriptErrorWitnessProgramWitnessEmpty)
|
||||
else {
|
||||
WitnessVersion0.rebuild(witness, program) match {
|
||||
WitnessVersion0.rebuild(witness, witnessSPKV0) match {
|
||||
case Right(rebuilt) =>
|
||||
Right((witness.stack.tail.map(ScriptConstant(_)), rebuilt))
|
||||
case Left(err) => Left(err)
|
||||
|
@ -440,7 +444,7 @@ sealed abstract class ScriptInterpreter {
|
|||
witnessVersion match {
|
||||
case WitnessVersion0 =>
|
||||
val either: Either[ScriptError, (Seq[ScriptToken], ScriptPubKey)] =
|
||||
rebuildV0(scriptWitness, witnessProgram)
|
||||
rebuildV0(scriptWitness, witnessSPK)
|
||||
either match {
|
||||
case Right((stack, scriptPubKey)) =>
|
||||
val newWTxSigComponent =
|
||||
|
|
|
@ -440,8 +440,7 @@ trait BitcoinScriptUtil {
|
|||
case w: WitnessScriptPubKey =>
|
||||
txSignatureComponent match {
|
||||
case wtxSigComponent: WitnessTxSigComponent =>
|
||||
val scriptE = w.witnessVersion.rebuild(wtxSigComponent.witness,
|
||||
w.witnessProgram)
|
||||
val scriptE = w.witnessVersion.rebuild(wtxSigComponent.witness, w)
|
||||
parseScriptEither(scriptE)
|
||||
case rWTxSigComponent: WitnessTxSigComponentRebuilt =>
|
||||
rWTxSigComponent.scriptPubKey.asm
|
||||
|
@ -492,7 +491,7 @@ trait BitcoinScriptUtil {
|
|||
case w: WitnessScriptPubKey =>
|
||||
val wtx = spendingTransaction.asInstanceOf[WitnessTransaction]
|
||||
val scriptT =
|
||||
w.witnessVersion.rebuild(wtx.witness.witnesses(idx), w.witnessProgram)
|
||||
w.witnessVersion.rebuild(wtx.witness.witnesses(idx), w)
|
||||
parseScriptEither(scriptT)
|
||||
|
||||
case _: P2PKHScriptPubKey | _: P2PKScriptPubKey |
|
||||
|
|
Loading…
Add table
Reference in a new issue