mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-20 10:13:26 +01:00
change true/false match to if/else in SpliceInterpreter, combine multiple opCode require clauses into a single clause
This commit is contained in:
parent
c939fe3d3e
commit
c1ae07b5a1
@ -13,7 +13,7 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
|
||||
|
||||
/** Returns 1 if the inputs are exactly equal, 0 otherwise. */
|
||||
def opEqual(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_EQUAL, "Script operation must be OP_EQUAL")
|
||||
require(program.script.headOption.contains(OP_EQUAL), "Script operation must be OP_EQUAL")
|
||||
if (program.stack.size < 2) {
|
||||
ScriptProgram(program,ScriptErrorInvalidStackOperation)
|
||||
} else {
|
||||
@ -37,7 +37,7 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
|
||||
|
||||
/** Same as [[OP_EQUAL]], but runs [[OP_VERIFY]] afterward. */
|
||||
def opEqualVerify(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_EQUALVERIFY, "Script operation must be OP_EQUALVERIFY")
|
||||
require(program.script.headOption.contains(OP_EQUALVERIFY), "Script operation must be OP_EQUALVERIFY")
|
||||
if (program.stack.size > 1) {
|
||||
//first replace OP_EQUALVERIFY with OP_EQUAL and OP_VERIFY
|
||||
val simpleScript = OP_EQUAL :: OP_VERIFY :: program.script.tail
|
||||
|
@ -14,19 +14,19 @@ trait ConstantInterpreter extends BitcoinSLogger {
|
||||
|
||||
/** The next byte contains the number of bytes to be pushed onto the stack. */
|
||||
def opPushData1(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_PUSHDATA1, "Top of script stack must be OP_PUSHDATA1")
|
||||
require(program.script.headOption.contains(OP_PUSHDATA1), "Top of script stack must be OP_PUSHDATA1")
|
||||
opPushData(program)
|
||||
}
|
||||
|
||||
/** The next two bytes contain the number of bytes to be pushed onto the stack. */
|
||||
def opPushData2(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_PUSHDATA2, "Top of script stack must be OP_PUSHDATA2")
|
||||
require(program.script.headOption.contains(OP_PUSHDATA2), "Top of script stack must be OP_PUSHDATA2")
|
||||
opPushData(program)
|
||||
}
|
||||
|
||||
/** The next four bytes contain the number of bytes to be pushed onto the stack. */
|
||||
def opPushData4(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_PUSHDATA4, "Top of script stack must be OP_PUSHDATA4")
|
||||
require(program.script.headOption.contains(OP_PUSHDATA4), "Top of script stack must be OP_PUSHDATA4")
|
||||
opPushData(program)
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ trait ControlOperationsInterpreter extends BitcoinSLogger {
|
||||
|
||||
/** If the top stack value is not 0, the statements are executed. The top stack value is removed. */
|
||||
def opIf(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_IF, "Script top was not OP_IF")
|
||||
require(program.script.headOption.contains(OP_IF), "Script top was not OP_IF")
|
||||
val sigVersion = program.txSignatureComponent.sigVersion
|
||||
val flags = program.flags
|
||||
val minimalIfEnabled = ScriptFlagUtil.minimalIfEnabled(flags)
|
||||
@ -57,7 +57,7 @@ trait ControlOperationsInterpreter extends BitcoinSLogger {
|
||||
/** If the top stack value is 0, the statements are executed. The top stack value is removed. */
|
||||
def opNotIf(program : ScriptProgram) : ScriptProgram = {
|
||||
//TODO: Try and reduce this down to using OP_IF by inverting the stack top
|
||||
require(program.script.nonEmpty && program.script.head == OP_NOTIF, "Script top was not OP_NOTIF")
|
||||
require(program.script.headOption.contains(OP_NOTIF), "Script top was not OP_NOTIF")
|
||||
val binaryTree = parseBinaryTree(program.script)
|
||||
val sigVersion = program.txSignatureComponent.sigVersion
|
||||
val flags = program.flags
|
||||
@ -92,7 +92,7 @@ trait ControlOperationsInterpreter extends BitcoinSLogger {
|
||||
|
||||
/** Evaluates the [[OP_ELSE]] operator. */
|
||||
def opElse(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_ELSE, "First script opt must be OP_ELSE")
|
||||
require(program.script.headOption.contains(OP_ELSE), "First script opt must be OP_ELSE")
|
||||
if (!program.script.tail.contains(OP_ENDIF)) {
|
||||
logger.error("OP_ELSE does not have a OP_ENDIF")
|
||||
ScriptProgram(program,ScriptErrorUnbalancedConditional)
|
||||
@ -119,7 +119,7 @@ trait ControlOperationsInterpreter extends BitcoinSLogger {
|
||||
|
||||
/** Evaluates an [[OP_ENDIF]] operator. */
|
||||
def opEndIf(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_ENDIF, "Script top must be OP_ENDIF")
|
||||
require(program.script.headOption.contains(OP_ENDIF), "Script top must be OP_ENDIF")
|
||||
if (!checkMatchingOpIfOpNotIfOpEndIf(program.originalScript)) {
|
||||
//means we do not have a matching OP_IF for our OP_ENDIF
|
||||
logger.error("We do not have a matching OP_IF/OP_NOTIF for every OP_ENDIF we have")
|
||||
@ -132,13 +132,13 @@ trait ControlOperationsInterpreter extends BitcoinSLogger {
|
||||
* reducing their cost to the network. Currently it is usually considered non-standard (though valid) for a transaction to
|
||||
* have more than one OP_RETURN output or an OP_RETURN output with more than one pushdata op. */
|
||||
def opReturn(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_RETURN)
|
||||
require(program.script.headOption.contains(OP_RETURN))
|
||||
ScriptProgram(program,ScriptErrorOpReturn)
|
||||
}
|
||||
|
||||
/** Marks [[org.bitcoins.core.protocol.transaction.Transaction]] as invalid if top stack value is not true. */
|
||||
def opVerify(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_VERIFY, "Script top must be OP_VERIFY")
|
||||
require(program.script.headOption.contains(OP_VERIFY), "Script top must be OP_VERIFY")
|
||||
program.stack.nonEmpty match {
|
||||
case true =>
|
||||
logger.debug("Stack for OP_VERIFY: " + program.stack)
|
||||
|
@ -18,31 +18,31 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
|
||||
|
||||
/** The input is hashed twice: first with SHA-256 and then with RIPEMD-160. */
|
||||
def opHash160(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_HASH160, "Script operation must be OP_HASH160")
|
||||
require(program.script.headOption.contains(OP_HASH160), "Script operation must be OP_HASH160")
|
||||
executeHashFunction(program, CryptoUtil.sha256Hash160(_ : Seq[Byte]))
|
||||
}
|
||||
|
||||
/** The input is hashed using RIPEMD-160. */
|
||||
def opRipeMd160(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_RIPEMD160, "Script operation must be OP_RIPEMD160")
|
||||
require(program.script.headOption.contains(OP_RIPEMD160), "Script operation must be OP_RIPEMD160")
|
||||
executeHashFunction(program, CryptoUtil.ripeMd160(_ : Seq[Byte]))
|
||||
}
|
||||
|
||||
/** The input is hashed using SHA-256. */
|
||||
def opSha256(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_SHA256, "Script operation must be OP_SHA256")
|
||||
require(program.script.headOption.contains(OP_SHA256), "Script operation must be OP_SHA256")
|
||||
executeHashFunction(program, CryptoUtil.sha256(_ : Seq[Byte]))
|
||||
}
|
||||
|
||||
/** The input is hashed two times with SHA-256. */
|
||||
def opHash256(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_HASH256, "Script operation must be OP_HASH256")
|
||||
require(program.script.headOption.contains(OP_HASH256), "Script operation must be OP_HASH256")
|
||||
executeHashFunction(program, CryptoUtil.doubleSHA256(_ : Seq[Byte]))
|
||||
}
|
||||
|
||||
/** The input is hashed using SHA-1. */
|
||||
def opSha1(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_SHA1, "Script top must be OP_SHA1")
|
||||
require(program.script.headOption.contains(OP_SHA1), "Script top must be OP_SHA1")
|
||||
executeHashFunction(program, CryptoUtil.sha1(_ : Seq[Byte]))
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
|
||||
* [[https://github.com/bitcoin/bitcoin/blob/528472111b4965b1a99c4bcf08ac5ec93d87f10f/src/script/interpreter.cpp#L880]]
|
||||
*/
|
||||
def opCheckSig(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_CHECKSIG, "Script top must be OP_CHECKSIG")
|
||||
require(program.script.headOption.contains(OP_CHECKSIG), "Script top must be OP_CHECKSIG")
|
||||
program match {
|
||||
case preExecutionScriptProgram : PreExecutionScriptProgram =>
|
||||
opCheckSig(ScriptProgram.toExecutionInProgress(preExecutionScriptProgram))
|
||||
@ -128,7 +128,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
|
||||
|
||||
/** Runs [[OP_CHECKSIG]] with an [[OP_VERIFY]] afterwards. */
|
||||
def opCheckSigVerify(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_CHECKSIGVERIFY,
|
||||
require(program.script.headOption.contains(OP_CHECKSIGVERIFY),
|
||||
"Script top must be OP_CHECKSIGVERIFY")
|
||||
if (program.stack.size < 2) {
|
||||
logger.error("Stack must contain at least 3 items for OP_CHECKSIGVERIFY")
|
||||
@ -149,7 +149,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
|
||||
/** All of the signature checking words will only match signatures to the data
|
||||
* after the most recently-executed [[OP_CODESEPARATOR]]. */
|
||||
def opCodeSeparator(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_CODESEPARATOR, "Script top must be OP_CODESEPARATOR")
|
||||
require(program.script.headOption.contains(OP_CODESEPARATOR), "Script top must be OP_CODESEPARATOR")
|
||||
val e = program match {
|
||||
case e : PreExecutionScriptProgram =>
|
||||
opCodeSeparator(ScriptProgram.toExecutionInProgress(e))
|
||||
@ -175,7 +175,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
|
||||
*/
|
||||
@tailrec
|
||||
final def opCheckMultiSig(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_CHECKMULTISIG, "Script top must be OP_CHECKMULTISIG")
|
||||
require(program.script.headOption.contains(OP_CHECKMULTISIG), "Script top must be OP_CHECKMULTISIG")
|
||||
val flags = program.flags
|
||||
program match {
|
||||
case preExecutionScriptProgram : PreExecutionScriptProgram =>
|
||||
@ -297,7 +297,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger
|
||||
|
||||
/** Runs [[OP_CHECKMULTISIG]] with an [[OP_VERIFY]] afterwards */
|
||||
def opCheckMultiSigVerify(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.nonEmpty && program.script.head == OP_CHECKMULTISIGVERIFY, "Script top must be OP_CHECKMULTISIGVERIFY")
|
||||
require(program.script.headOption.contains(OP_CHECKMULTISIGVERIFY), "Script top must be OP_CHECKMULTISIGVERIFY")
|
||||
if (program.stack.size < 3) {
|
||||
logger.error("Stack must contain at least 3 items for OP_CHECKMULTISIGVERIFY")
|
||||
ScriptProgram(program,ScriptErrorInvalidStackOperation)
|
||||
|
@ -28,7 +28,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
||||
*/
|
||||
@tailrec
|
||||
final def opCheckLockTimeVerify(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY,
|
||||
require(program.script.headOption.contains(OP_CHECKLOCKTIMEVERIFY),
|
||||
"Script top must be OP_CHECKLOCKTIMEVERIFY")
|
||||
val input = program.txSignatureComponent.transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
|
||||
val transaction = program.txSignatureComponent.transaction
|
||||
|
@ -13,22 +13,18 @@ import org.bitcoins.core.util.BitcoinSLogger
|
||||
trait SpliceInterpreter extends BitcoinSLogger {
|
||||
|
||||
/** Pushes the string length of the top element of the stack (without popping it). */
|
||||
def opSize(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_SIZE, "Script top must be OP_SIZE")
|
||||
program.stack.size > 0 match {
|
||||
case true =>
|
||||
if (program.stack.head == OP_0) {
|
||||
ScriptProgram(program, OP_0 :: program.stack, program.script.tail)
|
||||
} else {
|
||||
val scriptNumber = program.stack.head match {
|
||||
case ScriptNumber.zero => ScriptNumber.zero
|
||||
case x : ScriptToken => ScriptNumber(x.bytes.size)
|
||||
}
|
||||
ScriptProgram(program, scriptNumber :: program.stack, program.script.tail)
|
||||
}
|
||||
case false =>
|
||||
logger.error("Must have at least 1 element on the stack for OP_SIZE")
|
||||
ScriptProgram(program,ScriptErrorInvalidStackOperation)
|
||||
def opSize(program: ScriptProgram): ScriptProgram = {
|
||||
require(program.script.headOption.contains(OP_SIZE), "Script top must be OP_SIZE")
|
||||
if (program.stack.nonEmpty) {
|
||||
if (program.stack.head == OP_0) return ScriptProgram(program, OP_0 :: program.stack, program.script.tail)
|
||||
val scriptNumber = program.stack.head match {
|
||||
case ScriptNumber.zero => ScriptNumber.zero
|
||||
case x: ScriptToken => ScriptNumber(x.bytes.size)
|
||||
}
|
||||
ScriptProgram(program, scriptNumber :: program.stack, program.script.tail)
|
||||
} else {
|
||||
logger.error("Must have at least 1 element on the stack for OP_SIZE")
|
||||
ScriptProgram(program, ScriptErrorInvalidStackOperation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user