mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
Add invariant to WitnessTransaction that says inputs.length == witnes… (#954)
* Add invariant to WitnessTransaction that says inputs.length == witnesses.length * Remove println * Address code review
This commit is contained in:
parent
535fd2d58f
commit
713d76ae67
@ -205,12 +205,13 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers {
|
||||
oldInput.sequence)
|
||||
|
||||
val updatedInputs = ubtx.inputs.updated(inputIndex.toInt, updatedInput)
|
||||
val witness = EmptyWitness.fromInputs(updatedInputs)
|
||||
|
||||
val uwtx = WitnessTransaction(ubtx.version,
|
||||
updatedInputs,
|
||||
ubtx.outputs,
|
||||
ubtx.lockTime,
|
||||
EmptyWitness)
|
||||
val uwtx = WitnessTransaction(version = ubtx.version,
|
||||
inputs = updatedInputs,
|
||||
outputs = ubtx.outputs,
|
||||
lockTime = ubtx.lockTime,
|
||||
witness = witness)
|
||||
|
||||
val wtxSigComp = {
|
||||
WitnessTxSigComponentP2SH(transaction = uwtx,
|
||||
|
@ -20,7 +20,7 @@ class TransactionWitnessSpec extends BitcoinSUnitTest {
|
||||
}
|
||||
|
||||
it must "be able to resize a witness to the given index" in {
|
||||
val empty = EmptyWitness
|
||||
val empty = EmptyWitness.fromN(0)
|
||||
val pubKey = ECPrivateKey.freshPrivateKey.publicKey
|
||||
val p2pkh = P2PKHScriptSignature(EmptyDigitalSignature, pubKey)
|
||||
val scriptWit = P2WPKHWitnessV0.fromP2PKHScriptSig(p2pkh)
|
||||
@ -31,7 +31,7 @@ class TransactionWitnessSpec extends BitcoinSUnitTest {
|
||||
|
||||
it must "fail to update a negative index witness" in {
|
||||
intercept[IndexOutOfBoundsException] {
|
||||
EmptyWitness.updated(-1, EmptyScriptWitness)
|
||||
EmptyWitness.fromN(0).updated(-1, EmptyScriptWitness)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,10 @@ case object EmptyTransaction extends BaseTransaction {
|
||||
}
|
||||
|
||||
sealed abstract class WitnessTransaction extends Transaction {
|
||||
require(
|
||||
inputs.length == witness.witnesses.length,
|
||||
s"Must have same amount of inputs and witnesses in witness tx, inputs=${inputs.length} witnesses=${witness.witnesses.length}"
|
||||
)
|
||||
|
||||
/** The txId for the witness transaction from satoshi's original serialization */
|
||||
override def txId: DoubleSha256Digest = {
|
||||
@ -224,7 +228,7 @@ object WitnessTransaction extends Factory[WitnessTransaction] {
|
||||
btx.inputs,
|
||||
btx.outputs,
|
||||
btx.lockTime,
|
||||
EmptyWitness)
|
||||
EmptyWitness.fromInputs(btx.inputs))
|
||||
case wtx: WitnessTransaction => wtx
|
||||
}
|
||||
}
|
||||
|
@ -55,10 +55,26 @@ sealed abstract class TransactionWitness extends NetworkElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to represent a transaction witness pre segwit, see BIP141 for details */
|
||||
case object EmptyWitness extends TransactionWitness {
|
||||
override val bytes: ByteVector = ByteVector.low(1)
|
||||
override val witnesses: Vector[ScriptWitness] = Vector.empty
|
||||
/** Each input (even if it does not spend a segwit output) needs to have a witness associated with it
|
||||
* in a [[WitnessTransaction]]. This helper case class is used to "fill in" [[EmptyScriptWitness]] for
|
||||
* the inputs that do not spend a [[org.bitcoins.core.protocol.script.WitnessScriptPubKeyV0 WitnessScriptPubKeyV0]]
|
||||
*
|
||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#specification
|
||||
* */
|
||||
case class EmptyWitness(witnesses: Vector[EmptyScriptWitness.type])
|
||||
extends TransactionWitness
|
||||
|
||||
object EmptyWitness {
|
||||
|
||||
/** Generates an empty witness with n [[EmptyScriptWitness]] inside it */
|
||||
def fromN(n: Int): EmptyWitness = {
|
||||
val wits = Vector.fill(n)(EmptyScriptWitness)
|
||||
new EmptyWitness(wits)
|
||||
}
|
||||
|
||||
def fromInputs(inputs: Seq[TransactionInput]): EmptyWitness = {
|
||||
fromN(inputs.length)
|
||||
}
|
||||
}
|
||||
|
||||
object TransactionWitness {
|
||||
@ -69,7 +85,8 @@ object TransactionWitness {
|
||||
if (witnesses.exists(_ != EmptyScriptWitness)) {
|
||||
TransactionWitnessImpl(witnesses)
|
||||
} else {
|
||||
EmptyWitness
|
||||
//means that everything must be a empty ScriptWitness
|
||||
EmptyWitness.fromN(witnesses.length)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,8 @@ sealed abstract class Signer[-SpendingInfo <: UTXOSpendingInfo] {
|
||||
spendingInfo.scriptWitnessOpt.map(scriptWit =>
|
||||
TransactionWitness(Vector(scriptWit)))
|
||||
val transactionWitness =
|
||||
transactionWitnessOpt.getOrElse(EmptyWitness)
|
||||
transactionWitnessOpt.getOrElse(
|
||||
EmptyWitness.fromInputs(btx.inputs))
|
||||
|
||||
WitnessTransaction(btx.version,
|
||||
btx.inputs,
|
||||
@ -407,11 +408,7 @@ sealed abstract class P2WPKHSigner extends BitcoinSigner[P2WPKHV0SpendingInfo] {
|
||||
|
||||
}
|
||||
case btx: BaseTransaction =>
|
||||
val wtx = WitnessTransaction(btx.version,
|
||||
btx.inputs,
|
||||
btx.outputs,
|
||||
btx.lockTime,
|
||||
EmptyWitness)
|
||||
val wtx = WitnessTransaction.toWitnessTx(btx)
|
||||
|
||||
sign(spendingInfoToSatisfy, wtx, isDummySignature)
|
||||
}
|
||||
@ -433,15 +430,7 @@ sealed abstract class P2WSHSigner extends BitcoinSigner[P2WSHV0SpendingInfo] {
|
||||
} else {
|
||||
val (_, output, inputIndex, _) = relevantInfo(spendingInfo, unsignedTx)
|
||||
|
||||
val wtx = unsignedTx match {
|
||||
case btx: BaseTransaction =>
|
||||
WitnessTransaction(btx.version,
|
||||
btx.inputs,
|
||||
btx.outputs,
|
||||
btx.lockTime,
|
||||
EmptyWitness)
|
||||
case wtx: WitnessTransaction => wtx
|
||||
}
|
||||
val wtx = WitnessTransaction.toWitnessTx(unsignedTx)
|
||||
|
||||
val signedSigComponentF = BitcoinSigner.sign(
|
||||
spendingInfo,
|
||||
|
Loading…
Reference in New Issue
Block a user