refactoring Channel code to use WitnessTransactions instead of BaseTransactions

This commit is contained in:
Chris Stewart 2017-08-10 13:13:34 -05:00
parent e4a81f0a2f
commit beafa86372
8 changed files with 42 additions and 35 deletions

View File

@ -1 +1,21 @@
import AssemblyKeys._ //test in assembly := {} testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "3") coverageExcludedPackages := ".*gen" coverageMinimum := 90 coverageFailOnMinimum := true mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => { case "logback.xml" => MergeStrategy.discard case x => old(x) } } assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false)
import AssemblyKeys._
//test in assembly := {}
testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "3")
coverageExcludedPackages := ".*gen"
coverageMinimum := 90
coverageFailOnMinimum := true
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => {
case "logback.xml" => MergeStrategy.discard
case x => old(x)
}
}
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false)
testOptions in Test += Tests.Argument("-oF")

View File

@ -175,26 +175,20 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
CryptoUtil.doubleSHA256(bytes).bytes
} else emptyHash.bytes
logger.debug("outPointHash: " + outPointHash.map(BitcoinSUtil.encodeHex(_)))
val sequenceHash: Seq[Byte] = if (isNotAnyoneCanPay && isNotSigHashNone && isNotSigHashSingle) {
val bytes = spendingTx.inputs.flatMap(_.sequence.bytes)
CryptoUtil.doubleSHA256(bytes).bytes
} else emptyHash.bytes
logger.debug("sequenceHash: " + sequenceHash.map(BitcoinSUtil.encodeHex(_)))
val outputHash: Seq[Byte] = if (isNotSigHashSingle && isNotSigHashNone) {
logger.debug("Not SIGHASH_SINGLE & Not SIGHASH_NONE")
val bytes = spendingTx.outputs.flatMap(o => BitcoinSUtil.decodeHex(RawTransactionOutputParser.write(o)))
CryptoUtil.doubleSHA256(bytes).bytes
} else if (HashType.isSIGHASH_SINGLE(hashType.num) && inputIndex < UInt32(spendingTx.outputs.size)) {
logger.debug("SIGHASH_SINGLE and input index < outputs size")
val output = spendingTx.outputs(inputIndexInt)
val bytes = CryptoUtil.doubleSHA256(RawTransactionOutputParser.write(output)).bytes
bytes
} else emptyHash.bytes
logger.debug("outputHash: " + outputHash.map(BitcoinSUtil.encodeHex(_)))
logger.debug("Script: " + script)
val scriptBytes = script.flatMap(_.bytes)
//helper function to flip endianness
val fe: Seq[Byte] => Seq[Byte] = {bytes: Seq[Byte] => BitcoinSUtil.decodeHex(BitcoinSUtil.flipEndianness(bytes)) }
@ -203,7 +197,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
spendingTx.inputs(inputIndexInt).previousOutput.bytes ++ CompactSizeUInt.calculateCompactSizeUInt(scriptBytes).bytes ++
scriptBytes ++ fe(amount.bytes) ++ fe(spendingTx.inputs(inputIndexInt).sequence.bytes) ++
outputHash ++ fe(spendingTx.lockTime.bytes) ++ hashType.num.bytes.reverse
logger.info("Serialization for signature for WitnessV0Sig: " + BitcoinSUtil.encodeHex(serializationForSig))
logger.debug("Serialization for signature for WitnessV0Sig: " + BitcoinSUtil.encodeHex(serializationForSig))
serializationForSig
}

View File

@ -58,7 +58,7 @@ sealed trait WitnessTxSigComponent extends TxSigComponent {
override def sigVersion = SigVersionWitnessV0
}
/** This represents checking the [[WitnessTransaction] against a P2WPKH or P2WSH ScriptPubKey */
/** This represents checking the [[WitnessTransaction]] against a P2WPKH or P2WSH ScriptPubKey */
sealed trait WitnessTxSigComponentRaw extends WitnessTxSigComponent {
override def scriptPubKey: WitnessScriptPubKey
@ -71,7 +71,7 @@ sealed trait WitnessTxSigComponentP2SH extends WitnessTxSigComponent {
override def scriptSignature: P2SHScriptSignature = {
val s = transaction.inputs(inputIndex.toInt).scriptSignature
require(s.isInstanceOf[P2SHScriptSignature], "Must have P2SHScriptSignature for P2SH(P2WSH())")
require(s.isInstanceOf[P2SHScriptSignature], "Must have P2SHScriptSignature for P2SH(P2WSH()), got: " + s)
s.asInstanceOf[P2SHScriptSignature]
}
@ -137,7 +137,7 @@ object WitnessTxSigComponent {
object WitnessTxSigComponentRaw {
private case class WitnessTxSigComponentRawImpl(transaction: WitnessTransaction,inputIndex: UInt32,
scriptPubKey: WitnessScriptPubKey, flags: Seq[ScriptFlag],
scriptPubKey: WitnessScriptPubKey, flags: Seq[ScriptFlag],
amount: CurrencyUnit) extends WitnessTxSigComponentRaw
def apply(transaction: WitnessTransaction,inputIndex: UInt32,

View File

@ -30,6 +30,8 @@ trait Policy {
ScriptVerifyLowS, ScriptVerifyWitness, ScriptVerifyMinimalIf, ScriptVerifyNullFail,
ScriptVerifyNullDummy, ScriptVerifyWitnessPubKeyType, ScriptVerifyDiscourageUpgradableWitnessProgram)
def standardFlags = standardScriptVerifyFlags
/** The number of confirmations for a payment to be considered as accepted */
def confirmations: Long = 6

View File

@ -134,11 +134,14 @@ sealed trait P2SHScriptSignature extends ScriptSignature {
//witness scriptPubKeys always have EmptyScriptSigs
if (WitnessScriptPubKey.isWitnessScriptPubKey(asm)) Success(EmptyScriptSignature)
else {
val asmWithoutRedeemScriptAndPushOp = asm(asm.size - 2) match {
case b : BytesToPushOntoStack => asm.dropRight(2)
case _ => asm.dropRight(3)
val asmWithoutRedeemScriptAndPushOp: Try[Seq[ScriptToken]] = Try {
asm(asm.size - 2) match {
case b: BytesToPushOntoStack => asm.dropRight(2)
case _ => asm.dropRight(3)
}
}
ScriptSignature.fromScriptPubKey(asmWithoutRedeemScriptAndPushOp,redeemScript)
val script = asmWithoutRedeemScriptAndPushOp.getOrElse(EmptyScriptSignature.asm)
ScriptSignature.fromScriptPubKey(script,redeemScript)
}
}

View File

@ -511,18 +511,10 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
wtx.witness.witnesses(txSigComponent.inputIndex.toInt).stack.nonEmpty
case _ : BaseTransaction => false
}
case w : WitnessTxSigComponent =>
val witnessedUsed = w.scriptPubKey match {
case _ : WitnessScriptPubKey => true
case _ : P2SHScriptPubKey =>
val p2shScriptSig = P2SHScriptSignature(txSigComponent.scriptSignature.bytes)
p2shScriptSig.redeemScript.isInstanceOf[WitnessScriptPubKey]
case _: CLTVScriptPubKey | _: CSVScriptPubKey | _: MultiSignatureScriptPubKey | _: NonStandardScriptPubKey
| _: P2PKScriptPubKey | _: P2PKHScriptPubKey | _: WitnessCommitment
| _: EscrowTimeoutScriptPubKey | EmptyScriptPubKey =>
w.witness.stack.isEmpty
}
!witnessedUsed
case _: WitnessTxSigComponentRaw => false
case w: WitnessTxSigComponentP2SH =>
val p2shScriptSig = P2SHScriptSignature(w.scriptSignature.bytes)
!p2shScriptSig.redeemScript.isInstanceOf[WitnessScriptPubKey]
case r: WitnessTxSigComponentRebuilt =>
r.transaction match {
case wtx: WitnessTransaction =>

View File

@ -6,7 +6,7 @@ import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.transaction.TransactionOutput
import org.bitcoins.core.serializers.script.{RawScriptPubKeyParser, ScriptParser}
import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSatoshisSerializer}
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil}
import org.bitcoins.core.util.BitcoinSUtil
import scala.annotation.tailrec
@ -49,9 +49,7 @@ trait RawTransactionOutputParser extends RawBitcoinSerializer[Seq[TransactionOut
val satoshis = CurrencyUnits.toSatoshis(output.value)
val satoshisHexWithoutPadding : String = BitcoinSUtil.flipEndianness(satoshis.hex)
val satoshisHex = addPadding(16,satoshisHexWithoutPadding)
logger.debug("satoshis: " + satoshisHex)
/* if (compactSizeUIntHex == "00") satoshisHex + compactSizeUIntHex
else */ satoshisHex + output.scriptPubKey.hex
satoshisHex + output.scriptPubKey.hex
}
/** Reads a single output from the given bytes, note this is different than [[org.bitcoins.core.serializers.transaction.RawTransactionOutputParser.read]]
@ -59,13 +57,11 @@ trait RawTransactionOutputParser extends RawBitcoinSerializer[Seq[TransactionOut
*/
def readSingleOutput(bytes: Seq[Byte]): TransactionOutput = {
val satoshisHex = BitcoinSUtil.encodeHex(bytes.take(8).reverse)
logger.debug("Satoshi hex: " + satoshisHex)
val satoshis = parseSatoshis(satoshisHex)
//it doesn't include itself towards the size, thats why it is incremented by one
val scriptPubKeyBytes = bytes.slice(8, bytes.size)
val scriptPubKey = RawScriptPubKeyParser.read(scriptPubKeyBytes)
val parsedOutput = TransactionOutput(satoshis,scriptPubKey)
logger.debug("Parsed output: " + parsedOutput)
parsedOutput
}

View File

@ -290,7 +290,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
}
def calculateScriptForSigning(txSignatureComponent: TxSigComponent, script: Seq[ScriptToken]): Seq[ScriptToken] = txSignatureComponent.scriptPubKey match {
case p2shScriptPubKey: P2SHScriptPubKey =>
case _: P2SHScriptPubKey =>
val p2shScriptSig = P2SHScriptSignature(txSignatureComponent.scriptSignature.bytes)
val sigsRemoved = removeSignaturesFromScript(p2shScriptSig.signatures,p2shScriptSig.redeemScript.asm)
sigsRemoved
@ -301,7 +301,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
parseScriptEither(scriptEither)
case rWTxSigComponent: WitnessTxSigComponentRebuilt =>
rWTxSigComponent.scriptPubKey.asm
case base : BaseTxSigComponent =>
case _: BaseTxSigComponent =>
//shouldn't have BaseTxSigComponent
//with a witness scriptPubKey
script