Removing script types from ScriptPubKey's - this was redundant

This commit is contained in:
Chris Stewart 2016-03-30 12:06:22 -05:00
parent 816205e5f5
commit 716758cd64
12 changed files with 97 additions and 35 deletions

View file

@ -3,7 +3,6 @@ package org.scalacoin.crypto
import org.scalacoin.currency.CurrencyUnits import org.scalacoin.currency.CurrencyUnits
import org.scalacoin.marshallers.RawBitcoinSerializerHelper import org.scalacoin.marshallers.RawBitcoinSerializerHelper
import org.scalacoin.marshallers.transaction.RawTransactionOutputParser import org.scalacoin.marshallers.transaction.RawTransactionOutputParser
import org.scalacoin.protocol.{MultiSignature, NonStandard, P2SH, P2PKH}
import org.scalacoin.protocol.script._ import org.scalacoin.protocol.script._
import org.scalacoin.protocol.transaction._ import org.scalacoin.protocol.transaction._
import org.scalacoin.script.constant.ScriptToken import org.scalacoin.script.constant.ScriptToken

View file

@ -23,7 +23,7 @@ sealed trait ScriptPubKey extends TransactionElement with BitcoinSLogger {
*/ */
def asm : Seq[ScriptToken] def asm : Seq[ScriptToken]
/** /* /**
* Returns the script type of this scriptPubKey * Returns the script type of this scriptPubKey
* @return * @return
*/ */
@ -35,7 +35,7 @@ sealed trait ScriptPubKey extends TransactionElement with BitcoinSLogger {
case _ if (asm.last == OP_CHECKMULTISIG) => MultiSignature case _ if (asm.last == OP_CHECKMULTISIG) => MultiSignature
case _ => NonStandard case _ => NonStandard
} }
} }*/
//the addresses that the bitcoins correlated to the output //the addresses that the bitcoins correlated to the output
def addresses : Seq[BitcoinAddress] = ??? def addresses : Seq[BitcoinAddress] = ???

View file

@ -26,6 +26,7 @@ sealed trait Transaction extends TransactionElement {
} }
case object EmptyTransaction extends Transaction { case object EmptyTransaction extends Transaction {
override def txId = "0000000000000000000000000000000000000000000000000000000000000000"
override def version = TransactionConstants.version override def version = TransactionConstants.version
override def inputs = Seq() override def inputs = Seq()
override def outputs = Seq() override def outputs = Seq()

View file

@ -22,7 +22,7 @@ sealed trait TransactionOutput extends TransactionElement {
override def hex = RawTransactionOutputParser.write(Seq(this)) override def hex = RawTransactionOutputParser.write(Seq(this))
} }
case object TransactionOutput extends TransactionOutput { case object EmptyTransactionOutput extends TransactionOutput {
override def value = CurrencyUnits.negativeSatoshi override def value = CurrencyUnits.negativeSatoshi
override def scriptPubKey = ScriptPubKeyFactory.empty override def scriptPubKey = ScriptPubKeyFactory.empty
} }

View file

@ -1,12 +1,14 @@
package org.scalacoin.script.locktime package org.scalacoin.script.locktime
import org.scalacoin.protocol.transaction.TransactionConstants
import org.scalacoin.script.constant.{ScriptNumberImpl, ScriptNumber} import org.scalacoin.script.constant.{ScriptNumberImpl, ScriptNumber}
import org.scalacoin.script.{ScriptProgramFactory, ScriptProgramImpl, ScriptProgram} import org.scalacoin.script.{ScriptProgramFactory, ScriptProgramImpl, ScriptProgram}
import org.scalacoin.util.BitcoinSLogger
/** /**
* Created by chris on 2/8/16. * Created by chris on 2/8/16.
*/ */
trait LockTimeInterpreter { trait LockTimeInterpreter extends BitcoinSLogger {
/** /**
@ -25,14 +27,18 @@ trait LockTimeInterpreter {
require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY, require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY,
"Script top must be OP_CHECKLOCKTIMEVERIFY") "Script top must be OP_CHECKLOCKTIMEVERIFY")
if (program.stack.size == 0) { if (program.stack.size == 0) {
logger.warn("Transaction validation failing in OP_CHECKLOCKTIMEVERIFY because we have no stack items")
ScriptProgramFactory.factory(program, program.stack, program.script.tail, false) ScriptProgramFactory.factory(program, program.stack, program.script.tail, false)
} else { } else if (program.transaction.inputs(program.inputIndex).sequence == TransactionConstants.sequence) {
logger.warn("Transaction validation failing in OP_CHECKLOCKTIMEVERIFY because the sequence number is 0xffffffff")
ScriptProgramFactory.factory(program, program.stack, program.script.tail, false)
}
else {
val isValid = program.stack.head match { val isValid = program.stack.head match {
case s : ScriptNumber if (s < ScriptNumberImpl(0)) => false 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 : 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 _ => false
case _ => true
} }
ScriptProgramFactory.factory(program,program.stack, program.script.tail, isValid) ScriptProgramFactory.factory(program,program.stack, program.script.tail, isValid)
} }

View file

@ -1,7 +1,6 @@
package org.scalacoin.marshallers.transaction package org.scalacoin.marshallers.transaction
import org.scalacoin.currency.{Satoshis, CurrencyUnits, Bitcoins} import org.scalacoin.currency.{Satoshis, CurrencyUnits, Bitcoins}
import org.scalacoin.protocol.{P2PKH, P2SH}
import org.scalacoin.protocol.transaction.TransactionOutput import org.scalacoin.protocol.transaction.TransactionOutput
import org.scalacoin.script.bitwise.OP_EQUAL import org.scalacoin.script.bitwise.OP_EQUAL
import org.scalacoin.script.constant.{BytesToPushOntoStackImpl, ScriptConstantImpl} import org.scalacoin.script.constant.{BytesToPushOntoStackImpl, ScriptConstantImpl}
@ -26,8 +25,6 @@ class RawTransactionOutputParserTest extends FlatSpec with MustMatchers with Raw
secondOutput.value must be (CurrencyUnits.toSatoshis(Bitcoins(0.02981145))) secondOutput.value must be (CurrencyUnits.toSatoshis(Bitcoins(0.02981145)))
firstOutput.scriptPubKey.asm must be (Seq(OP_HASH160, BytesToPushOntoStackImpl(20),ScriptConstantImpl("eda8ae08b5c9f973f49543e90a7c292367b3337c"), OP_EQUAL)) firstOutput.scriptPubKey.asm must be (Seq(OP_HASH160, BytesToPushOntoStackImpl(20),ScriptConstantImpl("eda8ae08b5c9f973f49543e90a7c292367b3337c"), OP_EQUAL))
secondOutput.scriptPubKey.asm must be (Seq(OP_HASH160,BytesToPushOntoStackImpl(20), ScriptConstantImpl("be2319b9060429692ebeffaa3be38497dc5380c8"), OP_EQUAL)) secondOutput.scriptPubKey.asm must be (Seq(OP_HASH160,BytesToPushOntoStackImpl(20), ScriptConstantImpl("be2319b9060429692ebeffaa3be38497dc5380c8"), OP_EQUAL))
firstOutput.scriptPubKey.scriptType must be (P2SH)
secondOutput.scriptPubKey.scriptType must be (P2SH)
} }
it must "seralialize a transaction output" in { it must "seralialize a transaction output" in {
@ -54,7 +51,5 @@ class RawTransactionOutputParserTest extends FlatSpec with MustMatchers with Raw
val rawTwoOutputs = "026c405d05000000001976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac809698000000000017a914af575bd77c5ce7eba3bd9ce6f89774713ae62c7987" val rawTwoOutputs = "026c405d05000000001976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac809698000000000017a914af575bd77c5ce7eba3bd9ce6f89774713ae62c7987"
val outputs = RawTransactionOutputParser.read(rawTwoOutputs) val outputs = RawTransactionOutputParser.read(rawTwoOutputs)
outputs.size must be (2) outputs.size must be (2)
outputs.head.scriptPubKey.scriptType must be (P2PKH)
outputs(1).scriptPubKey.scriptType must be (P2SH)
} }
} }

View file

@ -1,7 +1,6 @@
package org.scalacoin.protocol.script package org.scalacoin.protocol.script
import org.scalacoin.crypto.ECFactory import org.scalacoin.crypto.ECFactory
import org.scalacoin.protocol.{MultiSignature, P2SH, P2PKH}
import org.scalacoin.script.bitwise.OP_EQUALVERIFY import org.scalacoin.script.bitwise.OP_EQUALVERIFY
import org.scalacoin.script.constant.{ScriptConstantImpl, BytesToPushOntoStackImpl, ScriptToken} import org.scalacoin.script.constant.{ScriptConstantImpl, BytesToPushOntoStackImpl, ScriptToken}
import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160, OP_CODESEPARATOR} import org.scalacoin.script.crypto.{OP_CHECKSIG, OP_HASH160, OP_CODESEPARATOR}
@ -24,25 +23,4 @@ class ScriptPubKeyTest extends FlatSpec with MustMatchers {
scriptPubKey.asm must be (expectedAsm) scriptPubKey.asm must be (expectedAsm)
} }
it must "derive a P2PKH script type from a scriptPubKey" in {
scriptPubKey.scriptType must be (P2PKH)
}
it must "derive a P2SH script type for a scriptPubKey" in {
TestUtil.p2shScriptPubKey.scriptType must be (P2SH)
}
it must "derive a multisignature script type for a scriptPubKey" in {
val multiSigRawScriptPubKey = "5221025878e270211662a27181cf" +
"4d6ad4d2cf0e69a98a3815c086f587c7e9388d87182103fc85980e3fac1f3d" +
"8a5c3223c3ef5bffc1bd42d2cc42add8c3899cc66e7f1906210215b5bd0508" +
"69166a70a7341b4f216e268b7c6c7504576dcea2cce7d11cc9a35f53ae"
val multiSigScriptPubKey = ScriptPubKeyFactory.fromHex(multiSigRawScriptPubKey)
multiSigScriptPubKey.scriptType must be (MultiSignature)
}
} }

View file

@ -0,0 +1,19 @@
package org.scalacoin.protocol.transaction
import org.scalacoin.protocol.script.EmptyScriptSignature
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 3/30/16.
*/
class TransactionInputTest extends FlatSpec with MustMatchers {
"TransactionInput" must "define an empty transaction input" in {
EmptyTransactionInput.previousOutput must be (EmptyTransactionOutPoint)
EmptyTransactionInput.scriptSignature must be (EmptyScriptSignature)
EmptyTransactionInput.scriptSigCompactSizeUInt.num must be (0)
EmptyTransactionInput.scriptSigCompactSizeUInt.size must be (1)
EmptyTransactionInput.sequence must be (TransactionConstants.sequence)
}
}

View file

@ -0,0 +1,13 @@
package org.scalacoin.protocol.transaction
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 3/30/16.
*/
class TransactionOutPointTest extends FlatSpec with MustMatchers {
"TransactionOutPoint" must "define an empty transaction outpoint" in {
EmptyTransactionOutPoint.txId must be ("")
EmptyTransactionOutPoint.vout must be (-1)
}
}

View file

@ -0,0 +1,16 @@
package org.scalacoin.protocol.transaction
import org.scalacoin.currency.CurrencyUnits
import org.scalacoin.protocol.script.EmptyScriptPubKey
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 3/30/16.
*/
class TransactionOutputTest extends FlatSpec with MustMatchers {
"TransactionOutput" must "define an empty transaction output" in {
EmptyTransactionOutput.scriptPubKey must be (EmptyScriptPubKey)
EmptyTransactionOutput.value must be (CurrencyUnits.negativeSatoshi)
}
}

View file

@ -16,4 +16,11 @@ class TransactionTest extends FlatSpec with MustMatchers {
tx.txId must be ("cddda897b0e9322937ee1f4fd5d6147d60f04a0f4d3b461e4f87066ac3918f2a") tx.txId must be ("cddda897b0e9322937ee1f4fd5d6147d60f04a0f4d3b461e4f87066ac3918f2a")
} }
it must "have an empty transaction with the correct fields" in {
EmptyTransaction.inputs.isEmpty must be (true)
EmptyTransaction.outputs.isEmpty must be (true)
EmptyTransaction.lockTime must be (TransactionConstants.lockTime)
EmptyTransaction.txId must be ("0000000000000000000000000000000000000000000000000000000000000000")
}
} }

View file

@ -0,0 +1,28 @@
package org.scalacoin.script.locktime
import org.scalacoin.script.ScriptProgramFactory
import org.scalacoin.script.constant.OP_0
import org.scalacoin.util.TestUtil
import org.scalatest.{MustMatchers, FlatSpec}
/**
* Created by chris on 3/30/16.
*/
class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeInterpreter {
"LockTimeInterpreter" must "mark the transaction invalid if the stack is empty" in {
val stack = Seq()
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val program = ScriptProgramFactory.factory(TestUtil.testProgram,stack,script)
val newProgram = opCheckLockTimeVerify(program)
newProgram.isValid must be (false)
}
it must "mark the transaction invalid if the transaction's sequence number is set to the max" in {
val stack = Seq(OP_0)
val script = Seq(OP_CHECKLOCKTIMEVERIFY)
val program = ScriptProgramFactory.factory(TestUtil.testProgram,stack,script)
val newProgram = opCheckLockTimeVerify(program)
newProgram.isValid must be (false)
}
}