Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Nethermind/Ethereum.Trie.Test/StorageTrieTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/

using Nethermind.Core.Crypto;
using Nethermind.Core.Encoding;
using Nethermind.Store;
using NUnit.Framework;

Expand All @@ -33,6 +32,7 @@ public void Storage_trie_set_reset_with_empty()
Keccak rootBefore = tree.RootHash;
tree.Set(1, new byte[] { 1 });
tree.Set(1, new byte[] { });
tree.UpdateRootHash();
Keccak rootAfter = tree.RootHash;
Assert.AreEqual(rootBefore, rootAfter);
}
Expand All @@ -44,6 +44,7 @@ public void Storage_trie_set_reset_with_long_zero()
Keccak rootBefore = tree.RootHash;
tree.Set(1, new byte[] { 1 });
tree.Set(1, new byte[] { 0, 0, 0, 0, 0 });
tree.UpdateRootHash();
Keccak rootAfter = tree.RootHash;
Assert.AreEqual(rootBefore, rootAfter);
}
Expand All @@ -55,6 +56,7 @@ public void Storage_trie_set_reset_with_short_zero()
Keccak rootBefore = tree.RootHash;
tree.Set(1, new byte[] { 1 });
tree.Set(1, new byte[] { 0 });
tree.UpdateRootHash();
Keccak rootAfter = tree.RootHash;
Assert.AreEqual(rootBefore, rootAfter);
}
Expand Down
24 changes: 18 additions & 6 deletions src/Nethermind/Ethereum.Trie.Test/TrieTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ private void RunTest(TrieTest test, bool secure)
patriciaTree.Set(key, value);
}

patriciaTree.UpdateRootHash();
Assert.AreEqual(test.ExpectedRoot, patriciaTree.RootHash.ToString());
}

Expand All @@ -177,6 +178,7 @@ public void Tutorial_test_1()
new byte[] { 0x01, 0x01, 0x02 },
Rlp.Encode(new object[] { "hello" }));

patriciaTree.UpdateRootHash();
Assert.AreEqual("0x15da97c42b7ed2e1c0c8dab6a6d7e3d9dc0a75580bbc4f1f29c33996d1415dcc",
patriciaTree.RootHash.ToString());
}
Expand All @@ -189,6 +191,7 @@ public void Tutorial_test_1_keccak()
new byte[] { 0x01, 0x01, 0x02 },
Rlp.Encode(new object[] { "hello" }));

patriciaTree.Commit();
PatriciaTree another = new PatriciaTree(_db, patriciaTree.RootHash);
Assert.AreEqual(((Leaf)patriciaTree.Root).Key.ToString(), ((Leaf)another.Root).Key.ToString());
Assert.AreEqual(Keccak.Compute(((Leaf)patriciaTree.Root).Value),
Expand All @@ -207,6 +210,7 @@ public void Tutorial_test_2()
new byte[] { 0x01, 0x01, 0x02 },
Rlp.Encode(new object[] { "hellothere" }));

patriciaTree.Commit();
Assert.AreEqual("0x05e13d8be09601998499c89846ec5f3101a1ca09373a5f0b74021261af85d396",
patriciaTree.RootHash.ToString());
}
Expand All @@ -225,9 +229,10 @@ public void Tutorial_test_2b()

Extension extension = patriciaTree.Root as Extension;
Assert.NotNull(extension);
Branch branch = patriciaTree.GetNode(extension.NextNode) as Branch;
Branch branch = extension.NextNodeRef?.Node as Branch;
Assert.NotNull(branch);

patriciaTree.UpdateRootHash();
Assert.AreEqual("0xb5e187f15f1a250e51a78561e29ccfc0a7f48e06d19ce02f98dd61159e81f71d",
patriciaTree.RootHash.ToString());
}
Expand All @@ -246,7 +251,7 @@ public void Tutorial_test_2c()

Extension extension = patriciaTree.Root as Extension;
Assert.NotNull(extension);
Branch branch = patriciaTree.GetNode(extension.NextNode) as Branch;
Branch branch = extension.NextNodeRef?.Node as Branch;
Assert.NotNull(branch);
}

Expand All @@ -264,9 +269,10 @@ public void Tutorial_test_2d()

Extension extension = patriciaTree.Root as Extension;
Assert.NotNull(extension);
Branch branch = patriciaTree.GetNode(extension.NextNode) as Branch;
Branch branch = extension.NextNodeRef?.Node as Branch;
Assert.NotNull(branch);

patriciaTree.UpdateRootHash();
Assert.AreEqual("0x17fe8af9c6e73de00ed5fd45d07e88b0c852da5dd4ee43870a26c39fc0ec6fb3",
patriciaTree.RootHash.ToString());
}
Expand All @@ -287,6 +293,7 @@ public void Tutorial_test_3()
new byte[] { 0x01, 0x01, 0x02, 0x57 },
Rlp.Encode(new object[] { "jimbojones" }));

patriciaTree.Commit();
Assert.AreEqual("0xfcb2e3098029e816b04d99d7e1bba22d7b77336f9fe8604f2adfb04bcf04a727",
patriciaTree.RootHash.ToString());
}
Expand All @@ -303,14 +310,15 @@ public void Delete_on_empty()
{
PatriciaTree patriciaTree = new PatriciaTree(_db);
patriciaTree.Set(Keccak.Compute("1").Bytes, new byte[0]);
patriciaTree.Commit();
Assert.AreEqual(PatriciaTree.EmptyTreeHash, patriciaTree.RootHash);
}

[Test]
public void Assigning_null_value_in_branch_throws_an_exception()
{
// ReSharper disable once ObjectCreationAsStatement
Assert.Throws<ArgumentNullException>(() => new Branch(new KeccakOrRlp[16], null));
Assert.Throws<ArgumentNullException>(() => new Branch(new NodeRef[16], null));

Branch branch = new Branch();
Assert.Throws<ArgumentNullException>(() => branch.Value = null);
Expand All @@ -333,8 +341,10 @@ public void Delete_missing_resolved_on_extension()
PatriciaTree patriciaTree = new PatriciaTree(_db);
patriciaTree.Set(new Nibble[] { 1, 2, 3, 4 }, new byte[] { 1 });
patriciaTree.Set(new Nibble[] { 1, 2, 3, 4, 5 }, new byte[] { 2 });
patriciaTree.UpdateRootHash();
Keccak rootBefore = patriciaTree.RootHash;
patriciaTree.Set(new Nibble[] { 1, 2, 3 }, new byte[] { });
patriciaTree.UpdateRootHash();
Assert.AreEqual(rootBefore, patriciaTree.RootHash);
}

Expand All @@ -344,18 +354,20 @@ public void Delete_missing_resolved_on_leaf()
PatriciaTree patriciaTree = new PatriciaTree(_db);
patriciaTree.Set(Keccak.Compute("1234567").Bytes, new byte[] { 1 });
patriciaTree.Set(Keccak.Compute("1234501").Bytes, new byte[] { 2 });
patriciaTree.UpdateRootHash();
Keccak rootBefore = patriciaTree.RootHash;
patriciaTree.Set(Keccak.Compute("1234502").Bytes, new byte[0]);
patriciaTree.UpdateRootHash();
Assert.AreEqual(rootBefore, patriciaTree.RootHash);
}

[Test]
public void Lookup_in_empty_tree()
{
PatriciaTree tree = new PatriciaTree(new MemDb());
Assert.AreEqual(tree.Root, null);
Assert.AreEqual(tree.RootRef, null);
tree.Get(new byte[] { 1 });
Assert.AreEqual(tree.Root, null);
Assert.AreEqual(tree.RootRef, null);
}

public class TrieTestJson
Expand Down
5 changes: 5 additions & 0 deletions src/Nethermind/Nethermind.Blockchain/BlockProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ private void SetReceipts(Block block, TransactionReceipt[] receipts)
receiptTree?.Set(Rlp.Encode(i).Bytes, receiptRlp);
}

receiptTree?.UpdateRootHash();

block.Receipts = receipts;
block.Header.ReceiptsRoot = receiptTree?.RootHash ?? PatriciaTree.EmptyTreeHash;
block.Header.Bloom = receipts.Length > 0 ? TransactionProcessor.BuildBloom(receipts.SelectMany(r => r.Logs).ToArray()) : Bloom.Empty; // TODO not tested anywhere at the time of writing
Expand All @@ -117,6 +119,7 @@ private Keccak GetTransactionsRoot(Transaction[] transactions)
txTree.Set(Rlp.Encode(i).Bytes, transactionRlp);
}

txTree.UpdateRootHash();
return txTree.RootHash;
}

Expand Down Expand Up @@ -271,6 +274,8 @@ private Block ProcessOne(Block suggestedBlock, bool tryOnly) // TODO: refactor
_logger.Debug($"Committing block - state root {_stateProvider.StateRoot}");
}

_stateProvider.CommitTree();
_storageProvider.CommitTrees();
_dbProvider.Commit(_specProvider.GetSpec(suggestedBlock.Number));
return processedBlock;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Core/Address.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public Address(Hex hex)

if (hex.ByteLength != AddressLengthInBytes)
{
throw new ArgumentException($"{nameof(Address)} should be {AddressLengthInBytes} bytes long", nameof(hex));
throw new ArgumentException($"{nameof(Address)} should be {AddressLengthInBytes} bytes long and is {hex.ByteLength} bytes long", nameof(hex));
}

Hex = hex;
Expand Down
5 changes: 5 additions & 0 deletions src/Nethermind/Nethermind.Core/BlockHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ public BlockHeader(Keccak parentHash, Keccak ommersHash, Address beneficiary, Bi
public BigInteger? TotalDifficulty { get; set; }
public BigInteger? TotalTransactions { get; set; }

public static Keccak CalculateHash(Rlp headerRlp)
{
return Keccak.Compute(headerRlp);
}

public static Keccak CalculateHash(BlockHeader header)
{
return Keccak.Compute(Rlp.Encode(header));
Expand Down
1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Core/Bloom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Core/Crypto/Keccak.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public Keccak(Hex hex)
{
if (hex.ByteLength != Size)
{
throw new ArgumentException($"{nameof(Keccak)} must be {Size} bytes", nameof(hex));
throw new ArgumentException($"{nameof(Keccak)} must be {Size} bytes and was {hex.ByteLength} bytes", nameof(hex));
}

Bytes = hex;
Expand All @@ -45,7 +45,7 @@ public Keccak(byte[] bytes)
{
if (bytes.Length != Size)
{
throw new ArgumentException($"{nameof(Keccak)} must be {Size} bytes", nameof(bytes));
throw new ArgumentException($"{nameof(Keccak)} must be {Size} bytes and was {bytes.Length} bytes", nameof(bytes));
}

Bytes = bytes;
Expand Down
6 changes: 5 additions & 1 deletion src/Nethermind/Nethermind.Core/Encoding/NewHeaderDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ public class NewHeaderDecoder : INewRlpDecoder<BlockHeader>
{
public BlockHeader Decode(NewRlp.DecoderContext context, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
byte[] headerRlp = context.ReadSequenceRlp();
context.Position -= headerRlp.Length;

long headerSequenceLength = context.ReadSequenceLength();
long headerCheck = context.Position + headerSequenceLength;

Keccak parentHash = context.ReadKeccak();
Keccak ommersHash = context.ReadKeccak();
Address beneficiary = context.ReadAddress();
Expand Down Expand Up @@ -66,7 +70,7 @@ public BlockHeader Decode(NewRlp.DecoderContext context, RlpBehaviors rlpBehavio
blockHeader.GasUsed = (long)gasUsed;
blockHeader.MixHash = mixHash;
blockHeader.Nonce = (ulong)nonce;
blockHeader.Hash = BlockHeader.CalculateHash(blockHeader);
blockHeader.Hash = BlockHeader.CalculateHash(new Rlp(headerRlp));
return blockHeader;
}
}
Expand Down
24 changes: 13 additions & 11 deletions src/Nethermind/Nethermind.Core/Encoding/Rlp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using Nethermind.Core.Crypto;
Expand All @@ -26,9 +27,9 @@
namespace Nethermind.Core.Encoding
{
/// <summary>
/// https://github.com/ethereum/wiki/wiki/RLP
/// https://github.com/ethereum/wiki/wiki/RLP
/// </summary>
//[DebuggerStepThrough]
[DebuggerStepThrough]
public class Rlp : IEquatable<Rlp>
{
public static readonly Rlp OfEmptyByteArray = new Rlp(128);
Expand Down Expand Up @@ -94,13 +95,13 @@ public static T Decode<T>(DecodedRlp rlp, RlpBehaviors rlpBehaviors = RlpBehavio

return rlp.As<T>();
}

public static T[] DecodeArray<T>(Rlp rlp, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
DecodedRlp decodedRlp = Decode(rlp);
return DecodeArray<T>(decodedRlp, rlpBehaviors);
}

public static T[] DecodeArray<T>(DecodedRlp rlp, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
T[] array = new T[rlp.Items.Count];
Expand All @@ -126,7 +127,7 @@ public static Rlp[] ExtractRlpList(Rlp rlp)

private static Rlp[] ExtractRlpList(DecoderContext context)
{
var result = new List<Rlp>();
List<Rlp> result = new List<Rlp>();

while (context.CurrentIndex < context.MaxIndex)
{
Expand Down Expand Up @@ -156,7 +157,7 @@ private static Rlp[] ExtractRlpList(DecoderContext context)
if (prefix <= 183)
{
int length = prefix - 128;
var content = context.Pop(length);
byte[] content = context.Pop(length);
if (content.Length == 1 && content[0] < 128)
{
throw new RlpException($"Unexpected byte value {content[0]}");
Expand Down Expand Up @@ -187,8 +188,8 @@ private static Rlp[] ExtractRlpList(DecoderContext context)
}
}

var data = context.Pop(concatenationLength);
var itemBytes = new[] {prefix};
byte[] data = context.Pop(concatenationLength);
byte[] itemBytes = {prefix};
if (lenghtBytes != null)
{
itemBytes = itemBytes.Concat(lenghtBytes).ToArray();
Expand Down Expand Up @@ -415,12 +416,14 @@ public static Rlp Encode(bool value)
{
return value ? new Rlp(1) : new Rlp(128);
}



public static Rlp Encode(byte value)
{
return EncodeNumber(value);
}


public static Rlp Encode(long value)
{
return EncodeNumber(value);
Expand Down Expand Up @@ -626,7 +629,7 @@ public static Rlp Encode(ChainLevelInfo levelInfo)
elements[1] = Encode(levelInfo.BlockInfos);
return Encode(elements);
}

public static Rlp Encode(BlockInfo blockInfo)
{
Rlp[] elements = new Rlp[4];
Expand Down Expand Up @@ -673,7 +676,6 @@ public static Rlp Encode(Bloom bloom)

public static Rlp Encode(LogEntry logEntry)
{
// TODO: can be slightly optimized in place
return Encode(
Encode(logEntry.LoggersAddress),
Encode(logEntry.Topics),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ public static byte[] SliceWithZeroPaddingEmptyOnError(this byte[] bytes, BigInte
public static int GetXxHashCode(this byte[] bytes)
{
LazyInitializer.EnsureInitialized(ref _xxHash, XXHash32.Create);
return BitConverter.ToInt32(_xxHash.ComputeHash(bytes), 0);
byte[] hash = _xxHash.ComputeHash(bytes);
return (hash[0] >> 24) | (hash[1] >> 16) | (hash[2] >> 8) | hash[3];
}
}
}
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Core/Extensions/Bytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
namespace Nethermind.Core.Extensions
{
// TODO: move to ByteArrayExtensions and ByteExtensions
[DebuggerStepThrough]
public static class Bytes
{
public static readonly IEqualityComparer<byte[]> EqualityComparer = new BytesEqualityComparer();
Expand Down
Loading