From fdc502acba9df74b26fc984cd4e3108f2769fe0a Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sat, 9 Jan 2016 18:20:50 -0600 Subject: [PATCH] Successfully parsing a byte array into an asm output script --- .../script/parsing/ScriptParser.scala | 31 +++++++++++++++---- .../script/parsing/ScriptParserTest.scala | 4 +-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/scala/org/scalacoin/script/parsing/ScriptParser.scala b/src/main/scala/org/scalacoin/script/parsing/ScriptParser.scala index 229cdcaaf8..36164f46d7 100644 --- a/src/main/scala/org/scalacoin/script/parsing/ScriptParser.scala +++ b/src/main/scala/org/scalacoin/script/parsing/ScriptParser.scala @@ -1,14 +1,15 @@ package org.scalacoin.script.parsing import org.scalacoin.script._ -import org.scalacoin.script.constant.{OP_0, ScriptConstantImpl, ScriptToken} +import org.scalacoin.script.constant._ +import org.scalacoin.util.ScalacoinUtil import scala.annotation.tailrec /** * Created by chris on 1/7/16. */ -trait ScriptParser { +trait ScriptParser extends ScalacoinUtil { /** * Parses an output script of a transaction * @param str @@ -36,9 +37,27 @@ trait ScriptParser { * @return */ def parse(bytes : List[Byte]) : List[ScriptToken] = { - val operations : List[ScriptToken] = for { - byte <- bytes - } yield ScriptOperationFactory.fromOpCode(byte).get - operations + + @tailrec + def loop(bytes : List[Byte], accum : List[ScriptToken]) : List[ScriptToken] = { + bytes match { + case h :: t => + val op = ScriptOperationFactory.fromOpCode(h).get + //means that we need to push x amount of bytes on to the stack + if (ScriptNumberFactory.operations.contains(op)) { + val (constant,tail) = pushConstant(ScriptNumberImpl(op.opCode),t) + loop(tail, constant :: accum) + } else loop(t, op :: accum) + case Nil => accum + } + + } + loop(bytes, List()).reverse + } + + def pushConstant(op : ScriptNumber, bytes : List[Byte]) : (ScriptConstant, List[Byte]) = { + val finalIndex = op.opCode + val constant : ScriptConstantImpl = ScriptConstantImpl(encodeHex(bytes.slice(0,finalIndex))) + (constant, bytes.slice(finalIndex,bytes.size)) } } diff --git a/src/test/scala/org/scalacoin/script/parsing/ScriptParserTest.scala b/src/test/scala/org/scalacoin/script/parsing/ScriptParserTest.scala index 5d18f87455..d9bd25326c 100644 --- a/src/test/scala/org/scalacoin/script/parsing/ScriptParserTest.scala +++ b/src/test/scala/org/scalacoin/script/parsing/ScriptParserTest.scala @@ -34,8 +34,8 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with it must "parse a p2pkh input script from a byte array to script tokens" in { /*val byteArray = TestUtil.p2pkhInputScript.getBytes.toList*/ - val byteArray : List[Byte] = decodeHex("76a914") - parse(byteArray) must be (List(OP_DUP, OP_HASH160, ScriptNumberImpl(20))) + val bytes : List[Byte] = decodeHex(TestUtil.p2pkhOutputScript) + parse(bytes) must be (TestUtil.p2pkhOutputScriptAsm) } }