MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.
MIT License
1.87k stars 846 forks source link

`Array size too big` after receiving block containing Ordinal NFT #1162

Closed lontivero closed 1 year ago

lontivero commented 1 year ago

This block made Wasabi filter creation process to halt because NBitcoin said that Array size too big however next time it run it past. I cannot make it fail locally so, it seems there is some special condition that is not deterministic.

2023-02-01 20:38:39.917 [537] ERROR     PeriodicRunner.ExecuteAsync (107)       System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'Array size too big')
   at NBitcoin.Protocol.VarString.StaticRead(BitcoinStream bs, Byte[]& bytes)
   at NBitcoin.WitScript.ReadCore(BitcoinStream stream)
   at NBitcoin.Witness.ReadWrite(BitcoinStream stream)
   at NBitcoin.Transaction.ReadWrite(BitcoinStream stream)
   at NBitcoin.BitcoinStream.ReadWrite[T](T& data)
   at NBitcoin.BitcoinStream.ReadWrite[T](List`1& list)
   at NBitcoin.Block.ReadWrite(BitcoinStream stream)
   at NBitcoin.Block.Parse(String hex, ConsensusFactory consensusFactory)
   at NBitcoin.RPC.RPCClient.GetBlockAsync(uint256 blockId, CancellationToken cancellationToken)
   at WalletWasabi.BitcoinCore.Rpc.RpcClientBase.GetBlockAsync(uint256 blockHash, CancellationToken cancellationToken)
   at WalletWasabi.Extensions.TaskExtensions.WithAwaitCancellationAsync[T](Task`1 task, CancellationToken cancellationToken)
   at WalletWasabi.Cache.IdempotencyRequestCache.GetCachedResponseAsync[TRequest,TResponse](TRequest request, ProcessRequestDelegateAsync`2 action, MemoryCacheEntryOptions options, CancellationToken cancellationToken)
   at WalletWasabi.Cache.IdempotencyRequestCache.GetCachedResponseAsync[TRequest,TResponse](TRequest request, ProcessRequestDelegateAsync`2 action, MemoryCacheEntryOptions options, CancellationToken cancellationToken)
   at WalletWasabi.BitcoinCore.Rpc.CachedRpcClient.GetBlockAsync(uint256 blockHash, CancellationToken cancellationToken)
   at WalletWasabi.Blockchain.Blocks.BlockNotifier.ActionAsync(CancellationToken cancel)
   at WalletWasabi.Bases.PeriodicRunner.ExecuteAsync(CancellationToken stoppingToken)

NBitcoin version: v7.0.14

This is the block: 0000000000000000000515e202c8ae73c8155fc472422d7593af87aa74f2cf3d

lontivero commented 1 year ago

Ok. To be honest, i have no proof that that block was the one that made it fail except for the fact that the time matches and that this is the first time i see such an exception in almost 5 years. Anyway, it could be something else too.

mjlamb commented 1 year ago

My BtcPay server seems to have come back alive by itself.

yahiheb commented 1 year ago

There is this huge tx in that block: https://mempool.space/tx/0301e0480b374b32851a9462db29dc19fe830a7f7d7a88b81612b9d42099c0ae

marceloceccon commented 1 year ago

This was thankfully fixed by @NicolasDorier on commit:

https://github.com/MetacoSA/NBitcoin/commit/aec688ba55700df3f3aa5eeb99eb08382b2ec8c3

lontivero commented 1 year ago

Umm that was added in version 7.0.16 and we have 7.0.14, however we are not stuck. I will do some better tests and go back with results.

lontivero commented 1 year ago

7.0.14 Failure

$dotnet fsi

Microsoft (R) F# Interactive version 12.4.0.0 for F# 7.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> #r "nuget:NBitcoin, 7.0.14";;
[Loading /home/*******/.packagemanagement/nuget/Cache/ed5af0b61ac615c41fd6fabcfdcd308332b56fd34a6a0e77f6378a7f200be1eb.fsx]
module FSI_0002.
       Ed5af0b61ac615c41fd6fabcfdcd308332b56fd34a6a0e77f6378a7f200be1eb

> open NBitcoin
- open System
- open System.IO;;
> let binBlock = File.ReadAllBytes "offending-block.hex";;
val binBlock: byte array =
  [|0uy; 0uy; 150uy; 40uy; 26uy; 43uy; 251uy; 207uy; 211uy; 15uy; 12uy; 193uy;
    41uy; 216uy; 218uy; 230uy; 71uy; 211uy; 205uy; 190uy; 109uy; 24uy; 189uy;
    141uy; 38uy; 96uy; 5uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 92uy;
    96uy; 180uy; 6uy; 48uy; 78uy; 14uy; 130uy; 138uy; 80uy; 99uy; 46uy; 144uy;
    216uy; 196uy; 217uy; 161uy; 203uy; 213uy; 156uy; 225uy; 174uy; 54uy; 66uy;
    100uy; 145uy; 191uy; 25uy; 222uy; 2uy; 137uy; 73uy; 201uy; 205uy; 218uy;
    99uy; 32uy; 39uy; 7uy; 23uy; 84uy; 112uy; 78uy; 208uy; 63uy; 1uy; 0uy; 0uy;
    0uy; 0uy; 1uy; 1uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy;
    0uy; ...|]

> Block.Load (binBlock, Network.Main);;
Binding session to '/home/******/.nuget/packages/nbitcoin/7.0.14/lib/net6.0/NBitcoin.dll'...
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'Array size too big')
   at NBitcoin.Protocol.VarString.StaticRead(BitcoinStream bs, Byte[]& bytes)
   at NBitcoin.BitcoinStream.ReadWriteAsVarString(Byte[]& bytes)
   at NBitcoin.WitScript.ReadPush(BitcoinStream stream)
   at NBitcoin.WitScript.ReadCore(BitcoinStream stream)
   at NBitcoin.WitScript.Load(BitcoinStream stream)
   at NBitcoin.Witness.ReadWrite(BitcoinStream stream)
   at NBitcoin.Transaction.ReadWrite(BitcoinStream stream)
   at NBitcoin.BitcoinStream.ReadWrite[T](T& data)
   at NBitcoin.BitcoinStream.ReadWrite[T](List`1& list)
   at NBitcoin.Block.ReadWrite(BitcoinStream stream)
   at NBitcoin.BitcoinSerializableExtensions.ReadWrite(IBitcoinSerializable serializable, Stream stream, Boolean serializing, ConsensusFactory consensusFactory, Nullable`1 version)
   at NBitcoin.BitcoinSerializableExtensions.ReadWrite(IBitcoinSerializable serializable, Byte[] bytes, ConsensusFactory consensusFactory, Nullable`1 version)
   at NBitcoin.Block.Load(Byte[] hex, ConsensusFactory consensusFactory)
   at NBitcoin.Block.Load(Byte[] hex, Network network)
   at <StartupCode$FSI_0005>.$FSI_0005.main@() in /home/lontivero/temp/offending-block/stdin:line 8
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
Stopped due to error
>

7.0.16 Succeed

$ dotnet fsi

Microsoft (R) F# Interactive version 12.4.0.0 for F# 7.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> #r "nuget:NBitcoin, 7.0.16";;
[Loading /home/******/.packagemanagement/nuget/Cache/e0cf6f4ced56078898977759b15f59b26edfaa4739ce74f671ca628e1ba71ed8.fsx]
module FSI_0002.
       E0cf6f4ced56078898977759b15f59b26edfaa4739ce74f671ca628e1ba71ed8

> open NBitcoin
- open System
- open System.IO;;
> let binBlock = File.ReadAllBytes "offending-block.hex";;
val binBlock: byte array =
  [|0uy; 0uy; 150uy; 40uy; 26uy; 43uy; 251uy; 207uy; 211uy; 15uy; 12uy; 193uy;
    41uy; 216uy; 218uy; 230uy; 71uy; 211uy; 205uy; 190uy; 109uy; 24uy; 189uy;
    141uy; 38uy; 96uy; 5uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 92uy;
    96uy; 180uy; 6uy; 48uy; 78uy; 14uy; 130uy; 138uy; 80uy; 99uy; 46uy; 144uy;
    216uy; 196uy; 217uy; 161uy; 203uy; 213uy; 156uy; 225uy; 174uy; 54uy; 66uy;
    100uy; 145uy; 191uy; 25uy; 222uy; 2uy; 137uy; 73uy; 201uy; 205uy; 218uy;
    99uy; 32uy; 39uy; 7uy; 23uy; 84uy; 112uy; 78uy; 208uy; 63uy; 1uy; 0uy; 0uy;
    0uy; 0uy; 1uy; 1uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy;
    0uy; ...|]

> let block = Block.Load (binBlock, Network.Main);;
Binding session to '/home/*****/.nuget/packages/nbitcoin/7.0.16/lib/net6.0/NBitcoin.dll'...
val block: Block

Still don't understand how it is that we are not affected.