From 699a28c9d72228f31de830acef9ffb9750d6fe8d Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 8 Jul 2020 09:44:17 +0200 Subject: [PATCH 1/2] Change nef checksum to double SHA256 (#1751) * Change to double SHA256 * Clean code * Revert change * Clean code * Fix checksum * Update NefFile.cs * Fix compile * Clean code Clean code Fix checksum Update NefFile.cs Fix compile * Optimize * Optimize * Fix Co-authored-by: erikzhang --- src/neo/SmartContract/NefFile.cs | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 815f2252fb..daa5d3b7f8 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -14,7 +14,7 @@ namespace Neo.SmartContract /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) | /// | ScriptHash | 20 bytes | ScriptHash for the script | /// +------------+-----------+------------------------------------------------------------+ - /// | Checksum | 4 bytes | Sha256 of the header (CRC) | + /// | Checksum | 4 bytes | First four bytes of double SHA256 hash | /// +------------+-----------+------------------------------------------------------------+ /// | Script | Var bytes | Var bytes for the payload | /// +------------+-----------+------------------------------------------------------------+ @@ -52,17 +52,24 @@ public class NefFile : ISerializable public byte[] Script { get; set; } private const int HeaderSize = - sizeof(uint) + // Magic - 32 + // Compiler - (sizeof(int) * 4) + // Version - UInt160.Length + // ScriptHash - sizeof(uint); // Checksum + sizeof(uint) + // Magic + 32 + // Compiler + (sizeof(int) * 4) + // Version + UInt160.Length; // ScriptHash public int Size => - HeaderSize + // Header - Script.GetVarSize(); // Script + HeaderSize + // Header + sizeof(uint) + // Checksum + Script.GetVarSize();// Script public void Serialize(BinaryWriter writer) + { + SerializeHeader(writer); + writer.Write(CheckSum); + writer.WriteVarBytes(Script ?? Array.Empty()); + } + + private void SerializeHeader(BinaryWriter writer) { writer.Write(Magic); writer.WriteFixedString(Compiler, 32); @@ -74,8 +81,6 @@ public void Serialize(BinaryWriter writer) writer.Write(Version.Revision); writer.Write(ScriptHash); - writer.Write(CheckSum); - writer.WriteVarBytes(Script ?? Array.Empty()); } public void Deserialize(BinaryReader reader) @@ -108,22 +113,17 @@ public void Deserialize(BinaryReader reader) /// /// File /// Return checksum - public static uint ComputeChecksum(NefFile file) + unsafe public static uint ComputeChecksum(NefFile file) { - using (var ms = new MemoryStream()) - using (var wr = new BinaryWriter(ms)) - { - file.Serialize(wr); - wr.Flush(); - - // Read header without CRC - - Span buffer = stackalloc byte[HeaderSize - sizeof(uint)]; - ms.Seek(0, SeekOrigin.Begin); - ms.Read(buffer); - - return BitConverter.ToUInt32(buffer.Sha256(), 0); - } + Span header = stackalloc byte[HeaderSize]; + fixed (byte* p = header) + using (UnmanagedMemoryStream ms = new UnmanagedMemoryStream(p, HeaderSize, HeaderSize, FileAccess.Write)) + using (BinaryWriter wr = new BinaryWriter(ms, Utility.StrictUTF8, false)) + { + file.SerializeHeader(wr); + wr.Flush(); + } + return BitConverter.ToUInt32(Crypto.Hash256(header), 0); } } } From 5952ad22e3d405bed14d51669a2b1e04151724ec Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 8 Jul 2020 12:44:09 +0200 Subject: [PATCH 2/2] Check witnesses on isStandard (#1754) * Check witness on isStandard * Add IsDeployed * Add IsPayable * Fix UT * format * Add coverage * Remove IsPayable, IsDeployed --- .../ApplicationEngine.Contract.cs | 23 ++++++++++++++++++- .../SmartContract/UT_InteropService.NEO.cs | 7 +++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index c537469da6..5b84938289 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -1,6 +1,7 @@ using Neo.Cryptography.ECC; using Neo.IO; using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; using Neo.VM; @@ -164,7 +165,27 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg internal bool IsStandardContract(UInt160 hash) { ContractState contract = Snapshot.Contracts.TryGet(hash); - return contract is null || contract.Script.IsStandardContract(); + + // It's a stored contract + + if (contract != null) return contract.Script.IsStandardContract(); + + // Try to find it in the transaction + + if (ScriptContainer is Transaction tx) + { + foreach (var witness in tx.Witnesses) + { + if (witness.ScriptHash == hash) + { + return witness.VerificationScript.IsStandardContract(); + } + } + } + + // It's not possible to determine if it's standard + + return false; } internal CallFlags GetCallFlags() diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 283fdc1d3f..5d78c4ebd5 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -110,7 +110,7 @@ public void TestAccount_IsStandard() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; - engine.IsStandardContract(new UInt160(hash)).Should().BeTrue(); + engine.IsStandardContract(new UInt160(hash)).Should().BeFalse(); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); @@ -118,6 +118,11 @@ public void TestAccount_IsStandard() engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(new byte[] { 0x01 }); engine.IsStandardContract(state.ScriptHash).Should().BeFalse(); + + state.Script = Contract.CreateSignatureRedeemScript(Blockchain.StandbyValidators[0]); + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(new byte[] { 0x01 }); + engine.IsStandardContract(state.ScriptHash).Should().BeTrue(); } [TestMethod]