Skip to content

Commit a3e75b2

Browse files
Allow Transactions without inputs to always be cloned and serialized if segwit not supported. (#1282)
1 parent 80fd7d9 commit a3e75b2

File tree

8 files changed

+58
-11
lines changed

8 files changed

+58
-11
lines changed

.github/workflows/CI.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
- uses: actions/checkout@v2
1414
- run: ./Build/CI/install-env.sh
1515
env:
16+
DOTNET_INSTALL_DIR: /usr/share/dotnet
1617
ADDITIONAL_RUNTIME: 6.0.36
1718
- run: ./Build/CI/tests.sh
1819
env:
@@ -29,6 +30,7 @@ jobs:
2930
sudo dpkg -i libssl1.0.0_1.0.2n-1ubuntu5_amd64.deb
3031
- run: ./Build/CI/install-env.sh
3132
env:
33+
DOTNET_INSTALL_DIR: /usr/share/dotnet
3234
ADDITIONAL_RUNTIME: 3.1.32
3335
- run: ./Build/CI/tests.sh
3436
env:
@@ -43,6 +45,7 @@ jobs:
4345
- uses: actions/checkout@v2
4446
- run: ./Build/CI/install-env.sh
4547
env:
48+
DOTNET_INSTALL_DIR: /usr/share/dotnet
4649
ADDITIONAL_RUNTIME: 6.0.36
4750
- run: ./Build/CI/tests.sh
4851
env:

Build/CI/install-env.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ chmod +x ./dotnet-install.sh
1515
[[ "${ADDITIONAL_RUNTIME:-}" ]] \
1616
&& echo "Additional Runtime needed: $ADDITIONAL_RUNTIME" \
1717
&& ./dotnet-install.sh --version "$ADDITIONAL_RUNTIME" --runtime dotnet --channel LTS
18+

Build/CI/tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export PATH="$PATH:$HOME/.dotnet"
77

88
export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
99
dotnet --info
10+
1011
dotnet build ./NBitcoin.Tests/NBitcoin.Tests.csproj \
1112
$BUILD_ARGS \
1213
-c Release \

NBitcoin.Altcoins/Dogecoin.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ public override TxOut CreateTxOut()
4646
{
4747
return new DogeTxOut();
4848
}
49+
50+
public override ProtocolCapabilities GetProtocolCapabilities(uint protocolVersion)
51+
{
52+
var capabilities = base.GetProtocolCapabilities(protocolVersion);
53+
capabilities.SupportWitness = false;
54+
return capabilities;
55+
}
56+
4957
protected override TransactionBuilder CreateTransactionBuilderCore(Network network)
5058
{
5159
// https://github.com/dogecoin/dogecoin/blob/master/doc/fee-recommendation.md

NBitcoin.Tests/transaction_tests.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,8 +845,8 @@ Transaction BuildTransaction(bool checkFee = true)
845845
return tx;
846846
};
847847
Transaction tx;
848-
849-
848+
849+
850850
if (dustPrevention)
851851
{
852852
feeAmount = scriptCoin2.Amount - dust + Money.Satoshis(1);
@@ -3086,6 +3086,26 @@ public void witnessHasPushSizeLimit()
30863086
Assert.Equal(ScriptError.PushSize, error);
30873087
}
30883088

3089+
[Fact]
3090+
[Trait("UnitTest", "UnitTest")]
3091+
public void CanParseCloneTxWithoutInput()
3092+
{
3093+
var tx = Transaction.Create(Dogecoin.Instance.Mainnet);
3094+
for (int i = 0; i < 5; i++)
3095+
{
3096+
tx.Outputs.Add(new TxOut(Money.Satoshis(500), new Key()));
3097+
}
3098+
tx.Clone();
3099+
var psbt = PSBT.FromTransaction(tx, Dogecoin.Instance.Mainnet);
3100+
3101+
tx = Transaction.Create(Network.Main);
3102+
for (int i = 0; i < 5; i++)
3103+
{
3104+
tx.Outputs.Add(new TxOut(Money.Satoshis(500), new Key()));
3105+
}
3106+
tx.Clone();
3107+
}
3108+
30893109
[Fact]
30903110
[Trait("UnitTest", "UnitTest")]
30913111
//http://brainwallet.org/#tx

NBitcoin/BitcoinStream.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public ConsensusFactory ConsensusFactory
164164
get
165165
{
166166

167-
return _ConsensusFactory ??= Consensus.Main.ConsensusFactory;;
167+
return _ConsensusFactory ??= Consensus.Main.ConsensusFactory;
168168
}
169169
set
170170
{

NBitcoin/IBitcoinSerializable.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,12 @@ public static void FromBytes(this IBitcoinSerializable serializable, byte[] byte
7878
public static byte[] ToBytes(this IBitcoinSerializable serializable, uint? version = null)
7979
{
8080
MemoryStream ms = new MemoryStream();
81+
var consensusFactory =
82+
(serializable as Transaction)?.GetConsensusFactory() ?? Consensus.Main.ConsensusFactory;
8183
serializable.ReadWrite(new BitcoinStream(ms, true)
8284
{
83-
ProtocolVersion = version
85+
ProtocolVersion = version,
86+
ConsensusFactory = consensusFactory
8487
});
8588
return ToArrayEfficient(ms);
8689
}

NBitcoin/Transaction.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,7 +1585,7 @@ public virtual void ReadWrite(BitcoinStream stream)
15851585
}
15861586
else
15871587
{
1588-
if (Inputs.Count == 0 && !stream.AllowNoInputs)
1588+
if (Inputs.Count == 0 && !stream.AllowNoInputs && witSupported)
15891589
throw new InvalidOperationException("The transaction must have at least one input");
15901590
stream.ReadWrite(ref nVersion);
15911591

@@ -1679,7 +1679,22 @@ public void PrecomputeHash(bool invalidateExisting, bool lazily)
16791679
public Transaction Clone(bool cloneCache)
16801680
{
16811681
var clone = GetConsensusFactory().CreateTransaction();
1682-
clone.ReadWrite(this.ToBytes(), GetConsensusFactory());
1682+
MemoryStream ms = new MemoryStream();
1683+
var txOptions = this.Inputs.Count is 0 ? TransactionOptions.None : TransactionOptions.All;
1684+
var stream = new BitcoinStream(ms, true)
1685+
{
1686+
TransactionOptions = txOptions,
1687+
ConsensusFactory = GetConsensusFactory(),
1688+
AllowNoInputs = true
1689+
};
1690+
this.ReadWrite(stream);
1691+
ms.Position = 0;
1692+
stream = new BitcoinStream(ms, false)
1693+
{
1694+
TransactionOptions = txOptions,
1695+
ConsensusFactory = GetConsensusFactory()
1696+
};
1697+
clone.ReadWrite(stream);
16831698
if (cloneCache)
16841699
clone._Hashes = _Hashes.ToArray();
16851700
return clone;
@@ -2463,11 +2478,7 @@ public virtual ConsensusFactory GetConsensusFactory()
24632478
}
24642479

24652480
public Transaction Clone()
2466-
{
2467-
var instance = GetConsensusFactory().CreateTransaction();
2468-
instance.ReadWrite(new BitcoinStream(this.ToBytes()) { ConsensusFactory = GetConsensusFactory() });
2469-
return instance;
2470-
}
2481+
=> Clone(false);
24712482

24722483
public void FromBytes(byte[] bytes)
24732484
{

0 commit comments

Comments
 (0)