diff --git a/src/Neo.IO/MemoryReader.cs b/src/Neo.IO/MemoryReader.cs index 7a5873efa1..ad18c0d616 100644 --- a/src/Neo.IO/MemoryReader.cs +++ b/src/Neo.IO/MemoryReader.cs @@ -33,7 +33,8 @@ public MemoryReader(ReadOnlyMemory memory) [MethodImpl(MethodImplOptions.AggressiveInlining)] private readonly void EnsurePosition(int move) { - if (_pos + move > _span.Length) throw new FormatException(); + if (_pos + move > _span.Length) + throw new FormatException($"Position {_pos} + Wanted {move} is exceeded boundary({_span.Length})"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -46,11 +47,12 @@ public readonly byte Peek() [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ReadBoolean() { - return ReadByte() switch + var value = ReadByte(); + return value switch { 0 => false, 1 => true, - _ => throw new FormatException() + _ => throw new FormatException($"Invalid boolean value: {value}") }; } @@ -188,7 +190,7 @@ public ulong ReadVarInt(ulong max = ulong.MaxValue) 0xff => ReadUInt64(), _ => b }; - if (value > max) throw new FormatException(); + if (value > max) throw new FormatException($"VarInt value is greater than max: {value}/{max}"); return value; } @@ -201,8 +203,10 @@ public string ReadFixedString(int length) while (i < end && _span[i] != 0) i++; var data = _span[_pos..i]; for (; i < end; i++) + { if (_span[i] != 0) - throw new FormatException(); + throw new FormatException($"The padding is not 0 at fixed string offset {i}"); + } _pos = end; return data.ToStrictUtf8String(); } diff --git a/src/Neo.Json/JNumber.cs b/src/Neo.Json/JNumber.cs index f68029fc8f..47303cafef 100644 --- a/src/Neo.Json/JNumber.cs +++ b/src/Neo.Json/JNumber.cs @@ -40,7 +40,7 @@ public class JNumber : JToken /// The value of the JSON token. public JNumber(double value = 0) { - if (!double.IsFinite(value)) throw new FormatException(); + if (!double.IsFinite(value)) throw new FormatException($"value is not finite: {value}"); Value = value; } diff --git a/src/Neo.Json/JToken.cs b/src/Neo.Json/JToken.cs index 5a89f84e74..44c0a95223 100644 --- a/src/Neo.Json/JToken.cs +++ b/src/Neo.Json/JToken.cs @@ -140,7 +140,7 @@ public int GetInt32() try { var json = Read(ref reader); - if (reader.Read()) throw new FormatException(); + if (reader.Read()) throw new FormatException("Read json token failed"); return json; } catch (JsonException ex) @@ -162,7 +162,7 @@ public int GetInt32() private static JToken? Read(ref Utf8JsonReader reader, bool skipReading = false) { - if (!skipReading && !reader.Read()) throw new FormatException(); + if (!skipReading && !reader.Read()) throw new FormatException("Read json token failed"); return reader.TokenType switch { JsonTokenType.False => false, diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index c918242e93..39a1c3756f 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -350,26 +350,32 @@ public static byte[] GetPrivateKeyFromNEP2(string nep2, byte[] passphrase, byte { ArgumentNullException.ThrowIfNull(nep2); ArgumentNullException.ThrowIfNull(passphrase); + byte[] data = nep2.Base58CheckDecode(); if (data.Length != 39 || data[0] != 0x01 || data[1] != 0x42 || data[2] != 0xe0) - throw new FormatException(); + throw new FormatException("Invalid NEP-2 key"); + byte[] addresshash = new byte[4]; Buffer.BlockCopy(data, 3, addresshash, 0, 4); + byte[] derivedkey = SCrypt.Generate(passphrase, addresshash, N, r, p, 64); byte[] derivedhalf1 = derivedkey[..32]; byte[] derivedhalf2 = derivedkey[32..]; Array.Clear(derivedkey, 0, derivedkey.Length); + byte[] encryptedkey = new byte[32]; Buffer.BlockCopy(data, 7, encryptedkey, 0, 32); Array.Clear(data, 0, data.Length); + byte[] prikey = XOR(Decrypt(encryptedkey, derivedhalf2), derivedhalf1); Array.Clear(derivedhalf1, 0, derivedhalf1.Length); Array.Clear(derivedhalf2, 0, derivedhalf2.Length); + ECPoint pubkey = ECCurve.Secp256r1.G * prikey; UInt160 script_hash = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); string address = script_hash.ToAddress(version); if (!Encoding.ASCII.GetBytes(address).Sha256().Sha256().AsSpan(0, 4).SequenceEqual(addresshash)) - throw new FormatException(); + throw new FormatException("The address hash in NEP-2 key is not valid"); return prikey; } @@ -382,8 +388,10 @@ public static byte[] GetPrivateKeyFromWIF(string wif) { ArgumentNullException.ThrowIfNull(wif); byte[] data = wif.Base58CheckDecode(); + if (data.Length != 34 || data[0] != 0x80 || data[33] != 0x01) - throw new FormatException(); + throw new FormatException("Invalid WIF key"); + byte[] privateKey = new byte[32]; Buffer.BlockCopy(data, 1, privateKey, 0, privateKey.Length); Array.Clear(data, 0, data.Length); diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs index d2019f01c8..34a138cc23 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs @@ -286,7 +286,11 @@ public void Save() public void Deserialize(ref MemoryReader reader) { Reset(0); - if (reader.ReadUInt32() != Block.Version) throw new FormatException(); + + var blockVersion = reader.ReadUInt32(); + if (blockVersion != Block.Version) + throw new FormatException($"Invalid block version: {blockVersion}/{Block.Version}"); + if (reader.ReadUInt32() != Block.Index) throw new InvalidOperationException(); Block.Header.Timestamp = reader.ReadUInt64(); Block.Header.Nonce = reader.ReadUInt64(); diff --git a/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs b/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs index ab151f5ab1..4ac4569650 100644 --- a/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs +++ b/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs @@ -39,8 +39,9 @@ protected ConsensusMessage(ConsensusMessageType type) public virtual void Deserialize(ref MemoryReader reader) { - if (Type != (ConsensusMessageType)reader.ReadByte()) - throw new FormatException(); + var type = reader.ReadByte(); + if (Type != (ConsensusMessageType)type) + throw new FormatException($"Invalid consensus message type: {type}"); BlockIndex = reader.ReadUInt32(); ValidatorIndex = reader.ReadByte(); ViewNumber = reader.ReadByte(); @@ -51,7 +52,7 @@ public static ConsensusMessage DeserializeFrom(ReadOnlyMemory data) ConsensusMessageType type = (ConsensusMessageType)data.Span[0]; Type t = typeof(ConsensusMessage); t = t.Assembly.GetType($"{t.Namespace}.{type}", false); - if (t is null) throw new FormatException(); + if (t is null) throw new FormatException($"Invalid consensus message type: {type}"); return (ConsensusMessage)data.AsSerializable(t); } diff --git a/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs b/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs index a3bb77cb76..121ee9d9b1 100644 --- a/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs +++ b/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs @@ -44,7 +44,7 @@ public override void Deserialize(ref MemoryReader reader) Nonce = reader.ReadUInt64(); TransactionHashes = reader.ReadSerializableArray(ushort.MaxValue); if (TransactionHashes.Distinct().Count() != TransactionHashes.Length) - throw new FormatException(); + throw new FormatException($"Transaction hashes are duplicate"); } public override bool Verify(ProtocolSettings protocolSettings) diff --git a/src/Plugins/SQLiteWallet/VerificationContract.cs b/src/Plugins/SQLiteWallet/VerificationContract.cs index d0160488ec..edcd7a09a1 100644 --- a/src/Plugins/SQLiteWallet/VerificationContract.cs +++ b/src/Plugins/SQLiteWallet/VerificationContract.cs @@ -27,7 +27,7 @@ public void Deserialize(ref MemoryReader reader) { ParameterList[i] = (ContractParameterType)span[i]; if (!Enum.IsDefined(ParameterList[i])) - throw new FormatException(); + throw new FormatException($"Invalid ContractParameterType: {ParameterList[i]}"); } Script = reader.ReadVarMemory().ToArray(); }