mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 02:39:18 +01:00
Optimizing toSeq inside of BinaryTree
This commit is contained in:
parent
372ec28a16
commit
a03d40f8d8
7 changed files with 87 additions and 8 deletions
|
@ -11,6 +11,7 @@ trait ScriptToken {
|
|||
def hex : String
|
||||
def bytes = ScalacoinUtil.decodeHex(hex)
|
||||
def bytesSize = bytes.size
|
||||
def toInt = Integer.parseInt(hex,16)
|
||||
}
|
||||
|
||||
trait ScriptOperation extends ScriptToken {
|
||||
|
|
|
@ -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.splice.{SpliceInterpreter, OP_SIZE}
|
||||
import org.scalacoin.script.{ScriptProgramImpl, ScriptProgram}
|
||||
import org.scalacoin.script.arithmetic.{ArithmeticInterpreter, OP_ADD}
|
||||
import org.scalacoin.script.bitwise.{OP_EQUAL, BitwiseInterpreter, OP_EQUALVERIFY}
|
||||
|
@ -18,7 +19,7 @@ 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 BitwiseInterpreter with ConstantInterpreter with ArithmeticInterpreter with SpliceInterpreter {
|
||||
|
||||
private def logger = LoggerFactory.getLogger(this.getClass().toString)
|
||||
|
||||
|
@ -105,6 +106,8 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
|
|||
//reserved operations
|
||||
case (nop : NOP) :: t => loop(ScriptProgramImpl(program.stack,t,program.transaction,program.altStack))
|
||||
|
||||
//splice operations
|
||||
case OP_SIZE :: t => loop(opSize(program))
|
||||
//no more script operations to run, True is represented by any representation of non-zero
|
||||
case Nil => program.stack.head != ScriptFalse
|
||||
case h :: t => throw new RuntimeException(h + " was unmatched")
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package org.scalacoin.script.splice
|
||||
|
||||
import org.scalacoin.script.{ScriptOperationFactory, ScriptProgramImpl, ScriptProgram}
|
||||
import org.scalacoin.script.constant.ScriptConstantImpl
|
||||
import org.scalacoin.util.ScalacoinUtil
|
||||
|
||||
/**
|
||||
* Created by chris on 2/4/16.
|
||||
*/
|
||||
trait SpliceInterpreter {
|
||||
|
||||
/**
|
||||
* Pushes the string length of the top element of the stack (without popping it).
|
||||
* @param program
|
||||
* @return
|
||||
*/
|
||||
def opSize(program : ScriptProgram) : ScriptProgram = {
|
||||
require(program.script.headOption.isDefined && program.script.head == OP_SIZE, "Script top must be OP_SIZE")
|
||||
require(program.stack.size > 0, "Must have at least 1 element on the stack for OP_SIZE")
|
||||
val stringSize = program.stack.head.bytes.size
|
||||
val hex = ScalacoinUtil.encodeHex(stringSize.toByte)
|
||||
val scriptOperation = ScriptOperationFactory.fromHex(hex)
|
||||
val size = if (scriptOperation.isDefined) scriptOperation.get else ScriptConstantImpl(hex)
|
||||
ScriptProgramImpl(size :: program.stack, program.script.tail, program.transaction,program.altStack)
|
||||
}
|
||||
|
||||
}
|
|
@ -141,12 +141,14 @@ trait BinaryTree[+T] {
|
|||
|
||||
|
||||
|
||||
|
||||
def toSeq : Seq[T] = {
|
||||
//TODO: Optimize this into a tailrec function
|
||||
//@tailrec
|
||||
def loop(tree : BinaryTree[T],accum : List[T]) : List[T] = tree match {
|
||||
case Leaf(x) => x :: accum
|
||||
case Leaf(x) => accum ++ List(x)
|
||||
case Empty => accum
|
||||
case Node(v,l,r) => v :: loop(l,List()) ++ loop(r,List())
|
||||
case Node(v,l,r) => loop(r,loop(l,accum ++ List(v)))
|
||||
}
|
||||
loop(this,List())
|
||||
}
|
||||
|
|
|
@ -54,13 +54,13 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp
|
|||
val source = scala.io.Source.fromFile("src/test/scala/org/scalacoin/script/interpreter/script_valid.json")
|
||||
|
||||
//use this to represent a single test case from script_valid.json
|
||||
/* val lines =
|
||||
val lines =
|
||||
"""
|
||||
|
|
||||
|[["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC"]]
|
||||
""".stripMargin*/
|
||||
|[["128", "SIZE 2 EQUAL", "P2SH,STRICTENC"]]
|
||||
""".stripMargin
|
||||
|
||||
val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
|
||||
//val lines = try source.getLines.filterNot(_.isEmpty).map(_.trim) mkString "\n" finally source.close()
|
||||
val json = lines.parseJson
|
||||
val testCasesOpt : Seq[Option[CoreTestCase]] = json.convertTo[Seq[Option[CoreTestCase]]]
|
||||
val testCases : Seq[CoreTestCase] = testCasesOpt.flatten
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package org.scalacoin.script.splice
|
||||
|
||||
import org.scalacoin.script.ScriptProgramImpl
|
||||
import org.scalacoin.script.bitwise.OP_EQUAL
|
||||
import org.scalacoin.script.constant.{OP_2, ScriptConstantImpl, OP_0}
|
||||
import org.scalacoin.util.TestUtil
|
||||
import org.scalatest.{MustMatchers, FlatSpec}
|
||||
|
||||
/**
|
||||
* Created by chris on 2/4/16.
|
||||
*/
|
||||
class SpliceInterpreterTest extends FlatSpec with MustMatchers with SpliceInterpreter {
|
||||
|
||||
"SpliceInterpreter" must "evaluate an OP_SIZE correctly" in {
|
||||
val stack = List(OP_0)
|
||||
val script = List(OP_SIZE)
|
||||
val program = ScriptProgramImpl(stack,script,TestUtil.transaction,List())
|
||||
val newProgram = opSize(program)
|
||||
newProgram.stack must be (List(OP_0,OP_0))
|
||||
newProgram.script.isEmpty must be (true)
|
||||
|
||||
}
|
||||
|
||||
it must "evaluate an OP_SIZE correctly with something of size 2 bytes" in {
|
||||
val stack = List(ScriptConstantImpl("80"))
|
||||
val script = List(OP_SIZE)
|
||||
val program = ScriptProgramImpl(stack,script,TestUtil.transaction,List())
|
||||
val newProgram = opSize(program)
|
||||
newProgram.stack must be (List(OP_2),ScriptConstantImpl("80"))
|
||||
newProgram.script.isEmpty must be (true)
|
||||
}
|
||||
}
|
|
@ -17,16 +17,30 @@ class BinaryTreeTest extends FlatSpec with MustMatchers {
|
|||
}
|
||||
|
||||
it must "convert a binary tree to to a list with node values" in {
|
||||
|
||||
//val script = List(OP_IF, OP_IF, OP_1, OP_ELSE, OP_0, OP_ENDIF, OP_ELSE, OP_IF, OP_0, OP_ELSE, OP_1, OP_ENDIF, OP_ENDIF)
|
||||
val bTree : BinaryTree[ScriptToken] =
|
||||
Node[ScriptToken](OP_IF,Node(OP_IF,Leaf(OP_1),Node(OP_ELSE,Leaf(OP_0),Leaf(OP_ENDIF))),
|
||||
Node(OP_ELSE,Node(OP_IF,Leaf(OP_0), Node(OP_ELSE,Leaf(OP_1),Leaf(OP_ENDIF))),Leaf(OP_ENDIF)))
|
||||
val script = List(OP_IF, OP_IF, OP_1, OP_ELSE, OP_0, OP_ENDIF, OP_ELSE, OP_IF, OP_0, OP_ELSE, OP_1, OP_ENDIF, OP_ENDIF)
|
||||
|
||||
bTree.toSeq.size must be (script.size)
|
||||
bTree.toSeq must be (script)
|
||||
}
|
||||
|
||||
it must "convert a simple binary tree to a sequence" in {
|
||||
val bTree = Node(1,Leaf(2), Leaf(3))
|
||||
val seq = bTree.toSeq
|
||||
seq must be (Seq(1,2,3))
|
||||
|
||||
val bTree1 = Node(1,Node(2,Empty,Empty), Node(3,Empty,Empty))
|
||||
val seq1 = bTree1.toSeq
|
||||
seq1 must be (List(1,2,3))
|
||||
|
||||
val bTree2 = Node(OP_IF,Node(OP_1,Empty,Empty), Node(OP_ELSE,Node(OP_2,Empty,Empty),Leaf(OP_ENDIF)))
|
||||
val seq2 = bTree2.toSeq
|
||||
seq2 must be (Seq(OP_IF,OP_1,OP_ELSE, OP_2,OP_ENDIF))
|
||||
}
|
||||
|
||||
|
||||
it must "find the first occurrence of a element in the tree" in {
|
||||
val tree = Node[Int](0,Node(1,Leaf(2),Leaf(3)), Node(1,Leaf(4), Leaf(5)))
|
||||
|
|
Loading…
Add table
Reference in a new issue