diff --git a/NBitcoin.Altcoins/Bitcoinplus.cs b/NBitcoin.Altcoins/Bitcoinplus.cs index 4f3ddfdcb5..16ce60464a 100644 --- a/NBitcoin.Altcoins/Bitcoinplus.cs +++ b/NBitcoin.Altcoins/Bitcoinplus.cs @@ -338,11 +338,7 @@ private void DeserializeTxn(BitcoinStream stream, bool witSupported) stream.ReadWrite(ref vinTemp); vinTemp.Transaction = this; - var hasNoDummy = (nVersionTemp & NoDummyInput) != 0 && vinTemp.Count == 0; - if (witSupported && hasNoDummy) - nVersionTemp = nVersionTemp & ~NoDummyInput; - - if (vinTemp.Count == 0 && witSupported && !hasNoDummy) + if (vinTemp.Count == 0 && witSupported) { /* We read a dummy or an empty vin. */ stream.ReadWrite(ref flags); @@ -392,8 +388,7 @@ private void DeserializeTxn(BitcoinStream stream, bool witSupported) private void SerializeTxn(BitcoinStream stream, bool witSupported) { byte flags = 0; - var version = (witSupported && (this.Inputs.Count == 0 && this.Outputs.Count > 0)) ? this.Version | NoDummyInput : this.Version; - stream.ReadWrite(ref version); + stream.ReadWrite(ref nVersion); // POS Timestamp var time = this.Time; diff --git a/NBitcoin.Altcoins/Litecoin.cs b/NBitcoin.Altcoins/Litecoin.cs index 9ee0b53fa6..2f7d42d22b 100644 --- a/NBitcoin.Altcoins/Litecoin.cs +++ b/NBitcoin.Altcoins/Litecoin.cs @@ -161,9 +161,7 @@ public override ConsensusFactory GetConsensusFactory() public override void ReadWrite(BitcoinStream stream) { var witSupported = (((uint)stream.TransactionOptions & (uint)TransactionOptions.Witness) != 0) && - stream.ProtocolCapabilities.SupportWitness; - - //var mwebSupported = false; //when mweb is supported in nbitcoin this is to be fixed + stream.ProtocolCapabilities.SupportWitness; byte flags = 0; if (!stream.Serializing) @@ -172,11 +170,8 @@ public override void ReadWrite(BitcoinStream stream) /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */ stream.ReadWrite(ref vin); vin.Transaction = this; - var hasNoDummy = (nVersion & NoDummyInput) != 0 && vin.Count == 0; - if (witSupported && hasNoDummy) - nVersion = nVersion & ~NoDummyInput; - if (vin.Count == 0 && witSupported && !hasNoDummy) + if (vin.Count == 0 && witSupported) { /* We read a dummy or an empty vin. */ stream.ReadWrite(ref flags); @@ -224,8 +219,10 @@ public override void ReadWrite(BitcoinStream stream) } else { - var version = (witSupported && (vin.Count == 0 && vout.Count > 0)) ? nVersion | NoDummyInput : nVersion; - stream.ReadWrite(ref version); + if (Inputs.Count == 0 && !stream.AllowNoInputs) + throw new InvalidOperationException("The transaction must have at least one input"); + + stream.ReadWrite(ref nVersion); if (witSupported) { @@ -238,8 +235,8 @@ public override void ReadWrite(BitcoinStream stream) if (flags != 0) { /* Use extended format in case witnesses are to be serialized. */ - TxInList vinDummy = new TxInList(); - stream.ReadWrite(ref vinDummy); + byte marker = 0; + stream.ReadWrite(ref marker); stream.ReadWrite(ref flags); } stream.ReadWrite(ref vin); diff --git a/NBitcoin.Altcoins/NBitcoin.Altcoins.csproj b/NBitcoin.Altcoins/NBitcoin.Altcoins.csproj index 67fa8d9fec..a93b462642 100644 --- a/NBitcoin.Altcoins/NBitcoin.Altcoins.csproj +++ b/NBitcoin.Altcoins/NBitcoin.Altcoins.csproj @@ -17,7 +17,7 @@ $(TargetFrameworkOverride) 1591;1573;1572;1584;1570;3021 true - 3.0.28 + 3.0.28.1 diff --git a/NBitcoin.Altcoins/Stratis.cs b/NBitcoin.Altcoins/Stratis.cs index 01caa455e7..60724cf762 100644 --- a/NBitcoin.Altcoins/Stratis.cs +++ b/NBitcoin.Altcoins/Stratis.cs @@ -360,11 +360,8 @@ private void DeserializeTxn(BitcoinStream stream, bool witSupported) // Try to read the vin. In case the dummy is there, this will be read as an empty vector. stream.ReadWrite(ref vinTemp); vinTemp.Transaction = this; - var hasNoDummy = (nVersionTemp & NoDummyInput) != 0 && vinTemp.Count == 0; - if (witSupported && hasNoDummy) - nVersionTemp = nVersionTemp & ~NoDummyInput; - if (vinTemp.Count == 0 && witSupported && !hasNoDummy) + if (vinTemp.Count == 0 && witSupported) { // We read a dummy or an empty vin. stream.ReadWrite(ref flags); @@ -414,8 +411,7 @@ private void DeserializeTxn(BitcoinStream stream, bool witSupported) private void SerializeTxn(BitcoinStream stream, bool witSupported) { byte flags = 0; - var version = (witSupported && (this.Inputs.Count == 0 && this.Outputs.Count > 0)) ? this.Version | NoDummyInput : this.Version; - stream.ReadWrite(ref version); + stream.ReadWrite(ref nVersion); // POS Timestamp var time = this.Time; diff --git a/NBitcoin.TestFramework/NBitcoin.TestFramework.csproj b/NBitcoin.TestFramework/NBitcoin.TestFramework.csproj index 9741835410..8d26da9b69 100644 --- a/NBitcoin.TestFramework/NBitcoin.TestFramework.csproj +++ b/NBitcoin.TestFramework/NBitcoin.TestFramework.csproj @@ -1,7 +1,7 @@  - 3.0.28 + 3.0.28.1 9.0 netstandard1.6;net472;netstandard2.0 netstandard2.1 diff --git a/NBitcoin.Tests/ChainTests.cs b/NBitcoin.Tests/ChainTests.cs index b37446f0d1..09e0467885 100644 --- a/NBitcoin.Tests/ChainTests.cs +++ b/NBitcoin.Tests/ChainTests.cs @@ -608,7 +608,9 @@ public ChainedBlock AppendBlock(ChainedBlock previous, params ConcurrentChain[] var nonce = RandomUtils.GetUInt32(); foreach (var chain in chains) { - var block = TestUtils.CreateFakeBlock(Network.Main.CreateTransaction()); + var tx = Network.Main.CreateTransaction(); + tx.Inputs.Add(); + var block = TestUtils.CreateFakeBlock(tx); block.Header.HashPrevBlock = previous == null ? chain.Tip.HashBlock : previous.HashBlock; block.Header.Nonce = nonce; if (!chain.TrySetTip(block.Header, out last)) diff --git a/NBitcoin.Tests/ColoredCoinsTests.cs b/NBitcoin.Tests/ColoredCoinsTests.cs index 65fe59d34c..0dbb373884 100644 --- a/NBitcoin.Tests/ColoredCoinsTests.cs +++ b/NBitcoin.Tests/ColoredCoinsTests.cs @@ -151,6 +151,7 @@ public void CanColorizeSpecScenario() Assert.True(destroyed[0].Id == a2.Id); var prior = Network.Main.CreateTransaction(); + prior.Inputs.Add(); prior.Outputs.Add(new TxOut(dust, a1.ScriptPubKey)); prior.Outputs.Add(new TxOut(dust, a2.ScriptPubKey)); prior.Outputs.Add(new TxOut(dust, h.ScriptPubKey)); diff --git a/NBitcoin.Tests/Generators/PSBTGenerator.cs b/NBitcoin.Tests/Generators/PSBTGenerator.cs index bc378e9182..d9f901c4e3 100644 --- a/NBitcoin.Tests/Generators/PSBTGenerator.cs +++ b/NBitcoin.Tests/Generators/PSBTGenerator.cs @@ -38,7 +38,7 @@ from psbt in SanePSBT(network) /// /// public static Gen SanePSBT(Network network) => - from inputN in Gen.Choose(0, 8) + from inputN in Gen.Choose(1, 8) from scripts in Gen.ListOf(inputN, ScriptGenerator.RandomScriptSig()) from txOuts in Gen.Sequence(scripts.Select(sc => OutputFromRedeem(sc))) from prevN in Gen.Choose(0, 5) diff --git a/NBitcoin.Tests/PSBTTests.cs b/NBitcoin.Tests/PSBTTests.cs index 25db349f38..dd69d875be 100644 --- a/NBitcoin.Tests/PSBTTests.cs +++ b/NBitcoin.Tests/PSBTTests.cs @@ -8,6 +8,8 @@ using System.Linq; using static NBitcoin.Tests.Comparer; using Xunit.Abstractions; +using System.Net.Http; +using System.Threading.Tasks; namespace NBitcoin.Tests { @@ -52,6 +54,7 @@ public static void ShouldCalculateBalanceOfHDKey() var bob = bobMaster.Derive(new KeyPath("4/5/6")); var funding = network.CreateTransaction(); + funding.Inputs.Add(); funding.Outputs.Add(Money.Coins(1.0m), alice); funding.Outputs.Add(Money.Coins(1.5m), bob); @@ -153,6 +156,15 @@ public static void ShouldParseValidDataDeterministically() Assert.Equal(psbt, psbt2, ComparerInstance); } } + + [Fact] + [Trait("UnitTest", "UnitTest")] + public void FixVersionParsingBug() + { + var tx = Transaction.Parse("39a75f190001010000000000000000000000000000000000000000000000000000000000000000ffffffff4903d7ae0d04970a256861627a637862fabe6d6d86846e235af48afb776d0a32cb278930b7dd601fb0e05011789ef233a3e0e7d1010000000000000012b299f4e40000000000ffffffffffffffff02ec12bb1200000000160014b6f3cfc20084e3b9f0d12b0e6f9da8fcbcf5a2d90000000000000000266a24aa21a9edc8a9c6157fb538507480083f8f5144e2f73d1bd9b6b5fabde17bd08ff524b7100120000000000000000000000000000000000000000000000000000000000000000000000000", Network.Main); + Assert.Equal("889d4fed1ec4a775d02082b5ff727f48d93013469db709d8d435e15b173118f3", tx.GetHash().ToString()); + } + [Fact] [Trait("UnitTest", "UnitTest")] public void AddCoinsShouldNotRemoveInfoFromPSBT() @@ -594,8 +606,9 @@ public void CanRebaseKeypathInPSBT() var accountExtKey = masterExtkey.Derive(new KeyPath("0'/0'/0'")); var accountRootedKeyPath = new KeyPath("0'/0'/0'").ToRootedKeyPath(masterExtkey); uint hardenedFlag = 0x80000000U; - retry: + retry: Transaction funding = masterExtkey.Network.CreateTransaction(); + funding.Inputs.Add(); funding.Outputs.Add(Money.Coins(2.0m), accountExtKey.Derive(0 | hardenedFlag).ScriptPubKey); funding.Outputs.Add(Money.Coins(2.0m), accountExtKey.Derive(1 | hardenedFlag).ScriptPubKey); diff --git a/NBitcoin.Tests/ProtocolTests.cs b/NBitcoin.Tests/ProtocolTests.cs index 67fb4dec32..1aa2b05320 100644 --- a/NBitcoin.Tests/ProtocolTests.cs +++ b/NBitcoin.Tests/ProtocolTests.cs @@ -1102,7 +1102,9 @@ public void CanConnectMultipleTimeToServer() public void CanRoundtripCmpctBlock() { Block block = Network.Main.Consensus.ConsensusFactory.CreateBlock(); - block.Transactions.Add(Network.Main.Consensus.ConsensusFactory.CreateTransaction()); + var tx = Network.Main.Consensus.ConsensusFactory.CreateTransaction(); + tx.Inputs.Add(); + block.Transactions.Add(tx); var cmpct = new CmpctBlockPayload(block); cmpct.Clone(); } diff --git a/NBitcoin.Tests/TestUtils.cs b/NBitcoin.Tests/TestUtils.cs index c5f9de5b58..7ed95e920b 100644 --- a/NBitcoin.Tests/TestUtils.cs +++ b/NBitcoin.Tests/TestUtils.cs @@ -47,7 +47,9 @@ public static Block CreateFakeBlock(Transaction tx) public static Block CreateFakeBlock() { - var block = TestUtils.CreateFakeBlock(Network.Main.CreateTransaction()); + var tx = Network.Main.CreateTransaction(); + tx.Inputs.Add(); + var block = TestUtils.CreateFakeBlock(tx); block.Header.HashPrevBlock = new uint256(RandomUtils.GetBytes(32)); block.Header.Nonce = RandomUtils.GetUInt32(); return block; diff --git a/NBitcoin.Tests/script_tests.cs b/NBitcoin.Tests/script_tests.cs index d1e2712749..05df96f837 100644 --- a/NBitcoin.Tests/script_tests.cs +++ b/NBitcoin.Tests/script_tests.cs @@ -149,6 +149,7 @@ public void BIP65_tests() private void BIP65_testsCore(LockTime target, LockTime now, bool expectedResult) { Transaction tx = Network.CreateTransaction(); + tx.Inputs.Add(); tx.Outputs.Add(new TxOut() { ScriptPubKey = new Script(Op.GetPushOp(target.Value), OpcodeType.OP_CHECKLOCKTIMEVERIFY) @@ -736,6 +737,7 @@ public void script_CHECKMULTISIG12() ); Transaction txFrom12 = Network.CreateTransaction(); + txFrom12.Inputs.Add(); txFrom12.Outputs.Add(new TxOut()); txFrom12.Outputs[0].ScriptPubKey = scriptPubKey12; @@ -780,6 +782,7 @@ public void script_CHECKMULTISIG23() var txFrom23 = Network.CreateTransaction(); + txFrom23.Inputs.Add(); txFrom23.Outputs.Add(new TxOut()); txFrom23.Outputs[0].ScriptPubKey = scriptPubKey23; diff --git a/NBitcoin.Tests/transaction_tests.cs b/NBitcoin.Tests/transaction_tests.cs index c7fcd72ee1..02e345c015 100644 --- a/NBitcoin.Tests/transaction_tests.cs +++ b/NBitcoin.Tests/transaction_tests.cs @@ -987,6 +987,7 @@ public void CanBuildShuffleColoredTransaction() var repo = new NoSqlColoredTransactionRepository(new NoSqlTransactionRepository(), new InMemoryNoSqlRepository()); var init = Network.CreateTransaction(); + init.Inputs.Add(); init.Outputs.Add("1.0", gold.PubKey); init.Outputs.Add("1.0", silver.PubKey); init.Outputs.Add("1.0", satoshi.PubKey); @@ -1278,6 +1279,7 @@ public void CanBuildColoredTransaction() var repo = new NoSqlColoredTransactionRepository(); var init = Network.CreateTransaction(); + init.Inputs.Add(); init.Outputs.Add("1.0", gold.PubKey); init.Outputs.Add("1.0", silver.PubKey); init.Outputs.Add("1.0", satoshi.PubKey); @@ -1374,6 +1376,7 @@ public void CanBuildColoredTransaction() //Gold receive 2.5 BTC tx = txBuilder.Network.Consensus.ConsensusFactory.CreateTransaction(); + tx.Inputs.Add(); tx.Outputs.Add("2.5", gold.PubKey); repo.Transactions.Put(tx.GetHash(), tx); @@ -1761,6 +1764,7 @@ public void CanEstimateFees() builder.SendEstimatedFees(rate); signed = builder.BuildTransaction(true); Assert.True(builder.Verify(signed, estimatedFees)); + Assert.Equal(1174, builder.EstimateSize(signed)); } private Coin RandomCoin(Money amount, IDestination dest, bool p2sh) @@ -1919,23 +1923,6 @@ void BitcoinStreamCoverageCore(TItem[] input, BitcoinStreamCoverageCoreDe AssertEx.CollectionEquals(before, input); } - [Fact] - [Trait("UnitTest", "UnitTest")] - public void CanSerializeInvalidTransactionsBackAndForth() - { - Transaction before = Network.CreateTransaction(); - var versionBefore = before.Version; - before.Outputs.Add(new TxOut()); - Transaction after = AssertClone(before); - Assert.Equal(before.Version, after.Version); - Assert.Equal(versionBefore, after.Version); - Assert.True(after.Outputs.Count == 1); - - before = Network.CreateTransaction(); - after = AssertClone(before); - Assert.Equal(before.Version, versionBefore); - } - private Transaction AssertClone(Transaction before) { Transaction after = before.Clone(); @@ -2095,6 +2082,7 @@ public void CanFilterUneconomicalCoins() var bob = new Key(); //P2SH(P2WSH) var previousTx = Network.CreateTransaction(); + previousTx.Inputs.Add(); previousTx.Outputs.Add(new TxOut(Money.Coins(1.0m), alice.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash)); var previousCoin = previousTx.Outputs.AsCoins().First(); @@ -2643,6 +2631,7 @@ public void CanBuildTransactionWithDustPrevention() var bob = new Key(); var alice = new Key(); var tx = Network.CreateTransaction(); + tx.Inputs.Add(); tx.Outputs.Add(Money.Coins(1.0m), bob); var coins = tx.Outputs.AsCoins().ToArray(); @@ -2837,6 +2826,7 @@ public void CanMutateSignature() public void CanUseLockTime() { var tx = Network.CreateTransaction(); + tx.Inputs.Add(); tx.LockTime = new LockTime(4); var clone = tx.Clone(); Assert.Equal(tx.LockTime, clone.LockTime); @@ -3067,6 +3057,7 @@ public void witnessHasPushSizeLimit() { var bob = new Key().GetWif(Network.RegTest); Transaction tx = Network.CreateTransaction(); + tx.Inputs.Add(); tx.Outputs.Add(new TxOut(Money.Coins(1.0m), bob.PubKey.ScriptPubKey.WitHash)); ScriptCoin coin = new ScriptCoin(tx.Outputs.AsCoins().First(), bob.PubKey.ScriptPubKey); diff --git a/NBitcoin/BitcoinStream.cs b/NBitcoin/BitcoinStream.cs index 0c5f687430..8b80af49fc 100644 --- a/NBitcoin/BitcoinStream.cs +++ b/NBitcoin/BitcoinStream.cs @@ -592,6 +592,7 @@ public void CopyParameters(BitcoinStream from) IsBigEndian = from.IsBigEndian; MaxArraySize = from.MaxArraySize; Type = from.Type; + AllowNoInputs = from.AllowNoInputs; } public SerializationType Type @@ -630,6 +631,13 @@ public System.Threading.CancellationToken ReadCancellationToken set; } + /// + /// Allows serialization of transactions with no inputs. + /// Such transactions are not valid for deserialization, but may still be useful, + /// for example, when computing a transaction hash or estimating size. + /// + public bool AllowNoInputs { get; set; } + public void ReadWriteAsVarInt(ref uint val) { if (Serializing) diff --git a/NBitcoin/IBitcoinSerializable.cs b/NBitcoin/IBitcoinSerializable.cs index 682910a2f4..42b31e61b2 100644 --- a/NBitcoin/IBitcoinSerializable.cs +++ b/NBitcoin/IBitcoinSerializable.cs @@ -32,6 +32,7 @@ public static void ReadWrite(this IBitcoinSerializable serializable, Stream stre public static int GetSerializedSize(this IBitcoinSerializable serializable, uint? version, SerializationType serializationType) { BitcoinStream s = new BitcoinStream(Stream.Null, true); + s.AllowNoInputs = true; s.Type = serializationType; s.ProtocolVersion = version; s.ReadWrite(serializable); @@ -40,6 +41,7 @@ public static int GetSerializedSize(this IBitcoinSerializable serializable, uint public static int GetSerializedSize(this IBitcoinSerializable serializable, TransactionOptions options) { var bms = new BitcoinStream(Stream.Null, true); + bms.AllowNoInputs = true; bms.TransactionOptions = options; serializable.ReadWrite(bms); return (int)bms.Counter.WrittenBytes; diff --git a/NBitcoin/NBitcoin.csproj b/NBitcoin/NBitcoin.csproj index 8c2ec5e652..6d2ef0c5dd 100644 --- a/NBitcoin/NBitcoin.csproj +++ b/NBitcoin/NBitcoin.csproj @@ -12,7 +12,7 @@ git - 7.0.42.1 + 7.0.42.2 9.0 diff --git a/NBitcoin/RPC/RPCClient.Wallet.cs b/NBitcoin/RPC/RPCClient.Wallet.cs index 8386039496..272ce5e0ed 100644 --- a/NBitcoin/RPC/RPCClient.Wallet.cs +++ b/NBitcoin/RPC/RPCClient.Wallet.cs @@ -380,8 +380,12 @@ private string ToHex(Transaction tx) // if there is inputs, then it can't be confusing if (tx.Inputs.Count > 0) return tx.ToHex(); - // if there is, do this ACK so that NBitcoin does not change the version number - return Encoders.Hex.EncodeData(tx.ToBytes(70012 - 1)); + + var ms = new MemoryStream(); + BitcoinStream bs = new BitcoinStream(ms, true); + bs.AllowNoInputs = true; + tx.ReadWrite(bs); + return Encoders.Hex.EncodeData(ms.ToArrayEfficient()); } diff --git a/NBitcoin/Transaction.cs b/NBitcoin/Transaction.cs index 6d07cb82e8..e234058ee1 100644 --- a/NBitcoin/Transaction.cs +++ b/NBitcoin/Transaction.cs @@ -339,6 +339,15 @@ public static TxIn CreateCoinbase(int height) txin.ScriptSig = new Script(Op.GetPushOp(height)) + OpcodeType.OP_0; return txin; } + + /// + /// Remove and from this input. + /// + public void RemoveSignatures() + { + ScriptSig = Script.Empty; + WitScript = WitScript.Empty; + } } public class TxOutCompressor : IBitcoinSerializable @@ -1445,6 +1454,12 @@ public static Transaction Parse(string hex, Network network) return Load(Encoders.Hex.DecodeData(hex), network); } + public void RemoveSignatures() + { + foreach (var input in Inputs) + input.RemoveSignatures(); + } + public static bool TryParse(string hex, Network network, out Transaction transaction) { if (hex == null) @@ -1513,9 +1528,6 @@ public TxOutList Outputs } } - //Since it is impossible to serialize a transaction with 0 input without problems during deserialization with wit activated, we fit a flag in the version to workaround it - protected const uint NoDummyInput = (1 << 27); - #region IBitcoinSerializable Members public virtual void ReadWrite(BitcoinStream stream) @@ -1530,11 +1542,8 @@ public virtual void ReadWrite(BitcoinStream stream) /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */ stream.ReadWrite(ref vin); vin.Transaction = this; - var hasNoDummy = (nVersion & NoDummyInput) != 0 && vin.Count == 0; - if (witSupported && hasNoDummy) - nVersion = nVersion & ~NoDummyInput; - if (vin.Count == 0 && witSupported && !hasNoDummy) + if (vin.Count == 0 && witSupported) { /* We read a dummy or an empty vin. */ stream.ReadWrite(ref flags); @@ -1574,8 +1583,9 @@ public virtual void ReadWrite(BitcoinStream stream) } else { - var version = (witSupported && (vin.Count == 0 && vout.Count > 0)) ? nVersion | NoDummyInput : nVersion; - stream.ReadWrite(ref version); + if (Inputs.Count == 0 && !stream.AllowNoInputs) + throw new InvalidOperationException("The transaction must have at least one input"); + stream.ReadWrite(ref nVersion); if (witSupported) { @@ -1624,6 +1634,7 @@ public uint256 GetHash() { TransactionOptions = TransactionOptions.None, ConsensusFactory = GetConsensusFactory(), + AllowNoInputs = true }; stream.SerializationTypeScope(SerializationType.Hash); this.ReadWrite(stream); diff --git a/NBitcoin/TransactionBuilder.cs b/NBitcoin/TransactionBuilder.cs index 5f96952c2a..392d850763 100644 --- a/NBitcoin/TransactionBuilder.cs +++ b/NBitcoin/TransactionBuilder.cs @@ -2426,10 +2426,9 @@ public void EstimateSizes(Transaction tx, out int witSize, out int baseSize) if (tx == null) throw new ArgumentNullException(nameof(tx)); var clone = tx.Clone(); - clone.Inputs.Clear(); - baseSize = clone.GetSerializedSize() - 1; - baseSize += new Protocol.VarInt((ulong)tx.Inputs.Count).GetSerializedSize(); - + clone.RemoveSignatures(); + baseSize = clone.GetSerializedSize(); + baseSize -= clone.Inputs.Count; // The varint to push scriptSig is accounted later witSize = 0; int nonWitnessCount = 0; bool hasWitness = tx.HasWitness; @@ -2443,10 +2442,8 @@ public void EstimateSizes(Transaction tx, out int witSize, out int baseSize) else nonWitnessCount++; EstimateScriptSigSize(coin, ref witSize, ref baseSize); - baseSize += (32 + 4) + 4; } - if (hasWitness) { witSize += 2; // 1 Dummy + 1 Flag