implementing OP_CHECKLOCKTIMEVERIFY script operation

This commit is contained in:
Chris Stewart 2016-02-08 09:01:58 -06:00
parent d02f259bc0
commit c0f709db37
2 changed files with 48 additions and 1 deletions

View file

@ -2,6 +2,7 @@ package org.scalacoin.script.interpreter
import org.scalacoin.protocol.script.{ScriptSignature, ScriptPubKey}
import org.scalacoin.protocol.transaction.Transaction
import org.scalacoin.script.locktime.{OP_CHECKLOCKTIMEVERIFY, LockTimeInterpreter}
import org.scalacoin.script.splice.{SpliceInterpreter, OP_SIZE}
import org.scalacoin.script.{ScriptProgramImpl, ScriptProgram}
import org.scalacoin.script.arithmetic._
@ -19,7 +20,8 @@ import scala.annotation.tailrec
* Created by chris on 1/6/16.
*/
trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with ControlOperationsInterpreter
with BitwiseInterpreter with ConstantInterpreter with ArithmeticInterpreter with SpliceInterpreter {
with BitwiseInterpreter with ConstantInterpreter with ArithmeticInterpreter with SpliceInterpreter
with LockTimeInterpreter {
private def logger = LoggerFactory.getLogger(this.getClass().toString)
@ -132,6 +134,10 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
//splice operations
case OP_SIZE :: t => loop(opSize(program))
//locktime operations
case OP_CHECKLOCKTIMEVERIFY :: t => loop(opCheckLockTimeVerify(program))
//no more script operations to run, True is represented by any representation of non-zero
case Nil => program.stack.headOption != Some(ScriptFalse)
case h :: t => throw new RuntimeException(h + " was unmatched")

View file

@ -0,0 +1,41 @@
package org.scalacoin.script.locktime
import org.scalacoin.script.constant.{ScriptNumberImpl, ScriptNumber}
import org.scalacoin.script.{ScriptProgramImpl, ScriptProgram}
/**
* Created by chris on 2/8/16.
*/
trait LockTimeInterpreter {
/**
* Marks transaction as invalid if the top stack item is greater than the transaction's nLockTime field,
* otherwise script evaluation continues as though an OP_NOP was executed. Transaction is also invalid if
* 1. the stack is empty; or
* 2. the top stack item is negative; or
* 3. the top stack item is greater than or equal to 500000000 while the transaction's nLockTime field is less than 500000000,
* or vice versa; or
* 4. the input's nSequence field is equal to 0xffffffff.
* The precise semantics are described in BIP 0065
* @param program
* @return
*/
def opCheckLockTimeVerify(program : ScriptProgram) : ScriptProgram = {
require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY,
"Script top must be OP_CHECKLOCKTIMEVERIFY")
if (program.stack.size == 0) {
ScriptProgramImpl(program.stack, program.script.tail, program.transaction, program.altStack,false)
} else {
val isValid = program.stack.head match {
case s : ScriptNumber if (s < ScriptNumberImpl(0)) => false
case s : ScriptNumber if (s > ScriptNumberImpl(500000000) && program.transaction.lockTime < 500000000) => false
case s : ScriptNumber if (s < ScriptNumberImpl(500000000) && program.transaction.lockTime > 500000000) => false
case s if (program.transaction.inputs.map(_.sequence == 0xffffffff).exists(_ == true)) => false
case _ => true
}
ScriptProgramImpl(program.stack, program.script.tail, program.transaction, program.altStack,isValid)
}
}
}