mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-22 22:36:34 +01:00
* Script Program apply method refactor part 5 (#760) * Formatting
This commit is contained in:
parent
f475808dbd
commit
9d16d723ae
10 changed files with 67 additions and 99 deletions
|
@ -20,15 +20,11 @@ class ScriptProgramFactoryTest extends FlatSpec with MustMatchers {
|
|||
val altStack = List(OP_1)
|
||||
|
||||
val modifiedStackProgram =
|
||||
ScriptProgram(TestUtil.testProgramExecutionInProgress,
|
||||
stack,
|
||||
ScriptProgram.Stack)
|
||||
TestUtil.testProgramExecutionInProgress.updateStack(stack)
|
||||
modifiedStackProgram.stack must be(stack)
|
||||
|
||||
val modifiedAltStack =
|
||||
ScriptProgram(TestUtil.testProgramExecutionInProgress,
|
||||
altStack,
|
||||
ScriptProgram.AltStack)
|
||||
TestUtil.testProgramExecutionInProgress.updateAltStack(altStack)
|
||||
|
||||
modifiedAltStack.altStack must be(altStack)
|
||||
}
|
||||
|
|
|
@ -24,13 +24,11 @@ class ScriptProgramTest extends FlatSpec with MustMatchers {
|
|||
ScriptProgram(TestUtil.testProgramExecutionInProgress, stack, script)
|
||||
program.stackTopIsTrue must be(false)
|
||||
|
||||
val program2 = ScriptProgram(program, List(OP_0), ScriptProgram.Stack)
|
||||
val program2 = program.updateStack(List(OP_0))
|
||||
program2.stackTopIsTrue must be(false)
|
||||
|
||||
//stack top should not be true for negative zero
|
||||
val program3 = ScriptProgram(program,
|
||||
List(ScriptNumber.negativeZero),
|
||||
ScriptProgram.Stack)
|
||||
val program3 = program.updateStack(List(ScriptNumber.negativeZero))
|
||||
program3.stackTopIsTrue must be(false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,10 +217,7 @@ class CryptoInterpreterTest extends FlatSpec with MustMatchers {
|
|||
it must "evaluate an OP_CODESEPARATOR" in {
|
||||
val stack = List()
|
||||
val script = Seq(OP_CODESEPARATOR)
|
||||
val program = ScriptProgram(
|
||||
ScriptProgram(TestUtil.testProgramExecutionInProgress, stack, script),
|
||||
script,
|
||||
ScriptProgram.OriginalScript)
|
||||
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack, script).updateOriginalScript(script)
|
||||
val newProgram = ScriptProgramTestUtil.toExecutionInProgressScriptProgram(
|
||||
CI.opCodeSeparator(program))
|
||||
newProgram.lastCodeSeparator must be(Some(0))
|
||||
|
|
|
@ -567,8 +567,7 @@ class StackInterpreterTest extends FlatSpec with MustMatchers {
|
|||
val altStack = List(OP_0)
|
||||
val program =
|
||||
ScriptProgram(TestUtil.testProgramExecutionInProgress, stack, script)
|
||||
val programWithAltStack =
|
||||
ScriptProgram(program, altStack, ScriptProgram.AltStack)
|
||||
val programWithAltStack = program.updateAltStack(altStack)
|
||||
val executedProgram = SI.opFromAltStack(programWithAltStack)
|
||||
executedProgram.stack must be(altStack)
|
||||
}
|
||||
|
|
|
@ -143,12 +143,33 @@ case class ExecutionInProgressScriptProgram(
|
|||
|
||||
/**
|
||||
* Removes the flags on the given [[org.bitcoins.core.script.ScriptProgram ScriptProgram]]
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def removeFlags(): ExecutionInProgressScriptProgram = {
|
||||
this.replaceFlags(Seq.empty)
|
||||
}
|
||||
|
||||
def updateStack(
|
||||
tokens: Seq[ScriptToken]): ExecutionInProgressScriptProgram = {
|
||||
this.copy(stack = tokens.toList)
|
||||
}
|
||||
|
||||
def updateAltStack(
|
||||
tokens: Seq[ScriptToken]): ExecutionInProgressScriptProgram = {
|
||||
this.copy(altStack = tokens.toList)
|
||||
}
|
||||
|
||||
def updateScript(
|
||||
tokens: Seq[ScriptToken]): ExecutionInProgressScriptProgram = {
|
||||
this.copy(script = tokens.toList)
|
||||
}
|
||||
|
||||
def updateOriginalScript(
|
||||
tokens: Seq[ScriptToken]): ExecutionInProgressScriptProgram = {
|
||||
this.copy(originalScript = tokens.toList)
|
||||
}
|
||||
|
||||
def updateLastCodeSeparator(
|
||||
newLastCodeSeparator: Int): ExecutionInProgressScriptProgram = {
|
||||
this.copy(lastCodeSeparator = Some(newLastCodeSeparator))
|
||||
|
@ -202,57 +223,22 @@ object ScriptProgram extends BitcoinSLogger {
|
|||
}
|
||||
|
||||
def apply(
|
||||
oldProgram: ExecutionInProgressScriptProgram,
|
||||
tokens: Seq[ScriptToken],
|
||||
indicator: UpdateIndicator): ExecutionInProgressScriptProgram = {
|
||||
indicator match {
|
||||
case Stack =>
|
||||
ExecutionInProgressScriptProgram(
|
||||
oldProgram.txSignatureComponent,
|
||||
tokens.toList,
|
||||
oldProgram.script,
|
||||
oldProgram.originalScript,
|
||||
oldProgram.altStack,
|
||||
oldProgram.flags,
|
||||
oldProgram.lastCodeSeparator
|
||||
)
|
||||
case Script =>
|
||||
ExecutionInProgressScriptProgram(
|
||||
oldProgram.txSignatureComponent,
|
||||
oldProgram.stack,
|
||||
tokens.toList,
|
||||
oldProgram.originalScript,
|
||||
oldProgram.altStack,
|
||||
oldProgram.flags,
|
||||
oldProgram.lastCodeSeparator
|
||||
)
|
||||
case AltStack =>
|
||||
ExecutionInProgressScriptProgram(
|
||||
oldProgram.txSignatureComponent,
|
||||
oldProgram.stack,
|
||||
oldProgram.script,
|
||||
oldProgram.originalScript,
|
||||
tokens.toList,
|
||||
oldProgram.flags,
|
||||
oldProgram.lastCodeSeparator
|
||||
)
|
||||
case OriginalScript =>
|
||||
ExecutionInProgressScriptProgram(oldProgram.txSignatureComponent,
|
||||
oldProgram.stack,
|
||||
oldProgram.script,
|
||||
tokens.toList,
|
||||
oldProgram.altStack,
|
||||
oldProgram.flags,
|
||||
oldProgram.lastCodeSeparator)
|
||||
}
|
||||
oldProgram: PreExecutionScriptProgram,
|
||||
stackTokens: Seq[ScriptToken],
|
||||
scriptTokens: Seq[ScriptToken]): PreExecutionScriptProgram = {
|
||||
val updatedStack = oldProgram.updateStack(stackTokens)
|
||||
val updatedScript = updatedStack.updateScript(scriptTokens)
|
||||
require(updatedStack.stack == stackTokens)
|
||||
require(updatedScript.script == scriptTokens)
|
||||
updatedScript
|
||||
}
|
||||
|
||||
def apply(
|
||||
oldProgram: ExecutionInProgressScriptProgram,
|
||||
stackTokens: Seq[ScriptToken],
|
||||
scriptTokens: Seq[ScriptToken]): ExecutionInProgressScriptProgram = {
|
||||
val updatedStack = ScriptProgram(oldProgram, stackTokens, Stack)
|
||||
val updatedScript = ScriptProgram(updatedStack, scriptTokens, Script)
|
||||
val updatedStack = oldProgram.updateStack(stackTokens)
|
||||
val updatedScript = updatedStack.updateScript(scriptTokens)
|
||||
require(updatedStack.stack == stackTokens)
|
||||
require(updatedScript.script == scriptTokens)
|
||||
updatedScript
|
||||
|
@ -266,7 +252,16 @@ object ScriptProgram extends BitcoinSLogger {
|
|||
tokens: Seq[ScriptToken],
|
||||
indicator: UpdateIndicator,
|
||||
lastCodeSeparator: Int): ExecutionInProgressScriptProgram = {
|
||||
val updatedIndicator = ScriptProgram(oldProgram, tokens, indicator)
|
||||
val updatedIndicator = indicator match {
|
||||
case Stack =>
|
||||
oldProgram.updateStack(tokens)
|
||||
case AltStack =>
|
||||
oldProgram.updateAltStack(tokens)
|
||||
case Script =>
|
||||
oldProgram.updateScript(tokens)
|
||||
case OriginalScript =>
|
||||
oldProgram.updateOriginalScript(tokens)
|
||||
}
|
||||
updatedIndicator.updateLastCodeSeparator(lastCodeSeparator)
|
||||
}
|
||||
|
||||
|
@ -296,11 +291,9 @@ object ScriptProgram extends BitcoinSLogger {
|
|||
stack: Seq[ScriptToken],
|
||||
script: Seq[ScriptToken],
|
||||
altStack: Seq[ScriptToken]): ExecutionInProgressScriptProgram = {
|
||||
val updatedProgramStack = ScriptProgram(oldProgram, stack, Stack)
|
||||
val updatedProgramScript =
|
||||
ScriptProgram(updatedProgramStack, script, Script)
|
||||
val updatedProgramAltStack =
|
||||
ScriptProgram(updatedProgramScript, altStack, AltStack)
|
||||
val updatedProgramStack = oldProgram.updateStack(stack)
|
||||
val updatedProgramScript = updatedProgramStack.updateScript(script)
|
||||
val updatedProgramAltStack = updatedProgramScript.updateAltStack(altStack)
|
||||
updatedProgramAltStack
|
||||
}
|
||||
|
||||
|
|
|
@ -307,10 +307,8 @@ sealed abstract class ArithmeticInterpreter {
|
|||
program.failExecution(ScriptErrorUnknownError)
|
||||
} else {
|
||||
val interpretedNumber = ScriptNumber(ScriptNumberUtil.toLong(s.hex))
|
||||
val newProgram = ScriptProgram(
|
||||
program,
|
||||
interpretedNumber :: program.stack.tail,
|
||||
ScriptProgram.Stack)
|
||||
val newProgram =
|
||||
program.updateStack(interpretedNumber :: program.stack.tail)
|
||||
performUnaryArithmeticOperation(newProgram, op)
|
||||
}
|
||||
case Some(_: ScriptToken) =>
|
||||
|
@ -360,26 +358,20 @@ sealed abstract class ArithmeticInterpreter {
|
|||
case (x: ScriptConstant, _: ScriptNumber) =>
|
||||
//interpret x as a number
|
||||
val interpretedNumber = ScriptNumber(x.hex)
|
||||
val newProgram = ScriptProgram(
|
||||
program,
|
||||
interpretedNumber :: program.stack.tail,
|
||||
ScriptProgram.Stack)
|
||||
val newProgram =
|
||||
program.updateStack(interpretedNumber :: program.stack.tail)
|
||||
performBinaryArithmeticOperation(newProgram, op)
|
||||
case (x: ScriptNumber, y: ScriptConstant) =>
|
||||
val interpretedNumber = ScriptNumber(y.hex)
|
||||
val newProgram = ScriptProgram(
|
||||
program,
|
||||
x :: interpretedNumber :: program.stack.tail,
|
||||
ScriptProgram.Stack)
|
||||
val newProgram =
|
||||
program.updateStack(x :: interpretedNumber :: program.stack.tail)
|
||||
performBinaryArithmeticOperation(newProgram, op)
|
||||
case (x: ScriptConstant, y: ScriptConstant) =>
|
||||
//interpret x and y as a number
|
||||
val interpretedNumberX = ScriptNumber(x.hex)
|
||||
val interpretedNumberY = ScriptNumber(y.hex)
|
||||
val newProgram = ScriptProgram(
|
||||
program,
|
||||
interpretedNumberX :: interpretedNumberY :: program.stack.tail.tail,
|
||||
ScriptProgram.Stack)
|
||||
val newProgram = program.updateStack(
|
||||
interpretedNumberX :: interpretedNumberY :: program.stack.tail.tail)
|
||||
performBinaryArithmeticOperation(newProgram, op)
|
||||
case (_: ScriptToken, _: ScriptToken) =>
|
||||
//pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
|
||||
|
|
|
@ -155,8 +155,7 @@ sealed abstract class ConstantInterpreter {
|
|||
ScriptNumber.zero :: program.stack,
|
||||
program.script.tail.tail)
|
||||
case _: ScriptToken =>
|
||||
pushScriptNumberBytesToStack(
|
||||
ScriptProgram(program, program.script, ScriptProgram.Script))
|
||||
pushScriptNumberBytesToStack(program.updateScript(program.script))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ sealed abstract class CryptoInterpreter {
|
|||
program.failExecution(ScriptErrorInvalidStackOperation)
|
||||
} else {
|
||||
val newScript = OP_CHECKSIG :: OP_VERIFY :: program.script.tail
|
||||
val newProgram = ScriptProgram(program, newScript, ScriptProgram.Script)
|
||||
val newProgram = program.updateScript(newScript)
|
||||
val programFromOpCheckSig = opCheckSig(newProgram)
|
||||
logger.debug(
|
||||
"Stack after OP_CHECKSIG execution: " + programFromOpCheckSig.stack)
|
||||
|
@ -264,7 +264,7 @@ sealed abstract class CryptoInterpreter {
|
|||
program.failExecution(ScriptErrorInvalidStackOperation)
|
||||
} else {
|
||||
val newScript = OP_CHECKMULTISIG :: OP_VERIFY :: program.script.tail
|
||||
val newProgram = ScriptProgram(program, newScript, ScriptProgram.Script)
|
||||
val newProgram = program.updateScript(newScript)
|
||||
val programFromOpCheckMultiSig = opCheckMultiSig(newProgram)
|
||||
logger.debug(
|
||||
"Stack after OP_CHECKMULTSIG execution: " + programFromOpCheckMultiSig.stack)
|
||||
|
|
|
@ -1016,8 +1016,7 @@ sealed abstract class ScriptInterpreter extends BitcoinSLogger {
|
|||
calcOpCount(opCount, OP_CHECKLOCKTIMEVERIFY))
|
||||
} //in this case, just reat OP_CLTV just like a NOP and remove it from the stack
|
||||
else {
|
||||
val programOrError =
|
||||
ScriptProgram(program, program.script.tail, ScriptProgram.Script)
|
||||
val programOrError = program.updateScript(program.script.tail)
|
||||
val newOpCount =
|
||||
calcOpCount(opCount, OP_CHECKLOCKTIMEVERIFY)
|
||||
(programOrError, newOpCount)
|
||||
|
@ -1040,8 +1039,7 @@ sealed abstract class ScriptInterpreter extends BitcoinSLogger {
|
|||
calcOpCount(opCount, OP_CHECKSEQUENCEVERIFY))
|
||||
} //in this case, just read OP_CSV just like a NOP and remove it from the stack
|
||||
else {
|
||||
val programOrError =
|
||||
ScriptProgram(program, program.script.tail, ScriptProgram.Script)
|
||||
val programOrError = program.updateScript(program.script.tail)
|
||||
val newOpCount =
|
||||
calcOpCount(opCount, OP_CHECKSEQUENCEVERIFY)
|
||||
(programOrError, newOpCount)
|
||||
|
|
|
@ -74,7 +74,7 @@ sealed abstract class LockTimeInterpreter {
|
|||
//if the number size is larger than 5 bytes the number is invalid
|
||||
program.failExecution(ScriptErrorUnknownError)
|
||||
} else if (checkLockTime(program, s)) {
|
||||
ScriptProgram(program, program.script.tail, ScriptProgram.Script)
|
||||
program.updateScript(program.script.tail)
|
||||
} else {
|
||||
logger.error(
|
||||
"Stack top locktime and transaction locktime number comparison failed")
|
||||
|
@ -82,9 +82,7 @@ sealed abstract class LockTimeInterpreter {
|
|||
}
|
||||
case s: ScriptConstant =>
|
||||
opCheckLockTimeVerify(
|
||||
ScriptProgram(program,
|
||||
ScriptNumber(s.hex) :: program.stack.tail,
|
||||
ScriptProgram.Stack))
|
||||
program.updateStack(ScriptNumber(s.hex) :: program.stack.tail))
|
||||
case _: ScriptToken => program.failExecution(ScriptErrorUnknownError)
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +119,7 @@ sealed abstract class LockTimeInterpreter {
|
|||
//see BIP68 for semantic of locktimeDisableFlag
|
||||
logger.info(
|
||||
"Locktime disable flag was set so OP_CHECKSEQUENCEVERIFY is treated as a NOP")
|
||||
ScriptProgram(program, program.script.tail, ScriptProgram.Script)
|
||||
program.updateScript(program.script.tail)
|
||||
case s: ScriptNumber
|
||||
if (isLockTimeBitOff(s) && program.txSignatureComponent.transaction.version < TransactionConstants.validLockVersion) =>
|
||||
logger.error(
|
||||
|
@ -140,9 +138,7 @@ sealed abstract class LockTimeInterpreter {
|
|||
}
|
||||
case s: ScriptConstant =>
|
||||
opCheckSequenceVerify(
|
||||
ScriptProgram(program,
|
||||
ScriptNumber(s.hex) :: program.stack.tail,
|
||||
ScriptProgram.Stack))
|
||||
program.updateStack(ScriptNumber(s.hex) :: program.stack.tail))
|
||||
case token: ScriptToken =>
|
||||
throw new RuntimeException(
|
||||
"Stack top must be either a ScriptConstant or a ScriptNumber, we got: " + token)
|
||||
|
|
Loading…
Add table
Reference in a new issue