Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove BlockBase and ConsensusData #2296

Merged
merged 3 commits into from
Feb 5, 2021
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
10 changes: 6 additions & 4 deletions src/neo/Cryptography/MerkleTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ public class MerkleTree
{
private readonly MerkleTreeNode root;

public int Depth { get; private set; }
public int Depth { get; }

internal MerkleTree(UInt256[] hashes)
{
if (hashes is null || hashes.Length == 0) throw new ArgumentException();
this.root = Build(hashes.Select(p => new MerkleTreeNode { Hash = p }).ToArray());
shargon marked this conversation as resolved.
Show resolved Hide resolved
if (root is null) return;
int depth = 1;
for (MerkleTreeNode i = root; i.LeftChild != null; i = i.LeftChild)
depth++;
Expand All @@ -25,7 +25,7 @@ internal MerkleTree(UInt256[] hashes)

private static MerkleTreeNode Build(MerkleTreeNode[] leaves)
{
if (leaves.Length == 0) throw new ArgumentException();
if (leaves.Length == 0) return null;
if (leaves.Length == 1) return leaves[0];

Span<byte> buffer = stackalloc byte[64];
Expand Down Expand Up @@ -60,7 +60,7 @@ private static UInt256 Concat(Span<byte> buffer, UInt256 hash1, UInt256 hash2)

public static UInt256 ComputeRoot(UInt256[] hashes)
{
if (hashes.Length == 0) throw new ArgumentException();
if (hashes.Length == 0) return UInt256.Zero;
if (hashes.Length == 1) return hashes[0];
MerkleTree tree = new MerkleTree(hashes);
return tree.root.Hash;
Expand All @@ -83,13 +83,15 @@ private static void DepthFirstSearch(MerkleTreeNode node, IList<UInt256> hashes)
// depth-first order
public UInt256[] ToHashArray()
{
if (root is null) return Array.Empty<UInt256>();
List<UInt256> hashes = new List<UInt256>();
DepthFirstSearch(root, hashes);
return hashes.ToArray();
}

public void Trim(BitArray flags)
{
if (root is null) return;
flags = new BitArray(flags);
flags.Length = 1 << (Depth - 1);
Trim(root, 0, Depth, flags);
Expand Down
30 changes: 13 additions & 17 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Akka.Configuration;
using Akka.IO;
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.IO.Actors;
using Neo.IO.Caching;
using Neo.Network.P2P;
Expand All @@ -13,7 +12,6 @@
using Neo.SmartContract.Native;
using Neo.VM;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
Expand Down Expand Up @@ -41,19 +39,19 @@ public class RelayResult { public IInventory Inventory; public VerifyResult Resu

public static readonly Block GenesisBlock = new Block
{
PrevHash = UInt256.Zero,
Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestampMS(),
Index = 0,
NextConsensus = Contract.GetBFTAddress(StandbyValidators),
Witness = new Witness
{
InvocationScript = Array.Empty<byte>(),
VerificationScript = new[] { (byte)OpCode.PUSH1 }
},
ConsensusData = new ConsensusData
Header = new Header
{
PrevHash = UInt256.Zero,
MerkleRoot = UInt256.Zero,
Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestampMS(),
Index = 0,
PrimaryIndex = 0,
Nonce = 2083236893
NextConsensus = Contract.GetBFTAddress(StandbyValidators),
Witness = new Witness
{
InvocationScript = Array.Empty<byte>(),
VerificationScript = new[] { (byte)OpCode.PUSH1 }
},
},
Transactions = Array.Empty<Transaction>()
};
Expand All @@ -63,7 +61,7 @@ public class RelayResult { public IInventory Inventory; public VerifyResult Resu
private static readonly object lockObj = new object();
private readonly NeoSystem system;
private readonly IActorRef txrouter;
private readonly ConcurrentDictionary<UInt256, Block> block_cache = new ConcurrentDictionary<UInt256, Block>();
private readonly Dictionary<UInt256, Block> block_cache = new Dictionary<UInt256, Block>();
private readonly Dictionary<uint, UnverifiedBlocksList> block_cache_unverified = new Dictionary<uint, UnverifiedBlocksList>();
internal readonly RelayCache RelayCache = new RelayCache(100);
private ImmutableHashSet<UInt160> extensibleWitnessWhiteList;
Expand All @@ -89,8 +87,6 @@ public static Blockchain Singleton

static Blockchain()
{
GenesisBlock.RebuildMerkleRoot();

using (ScriptBuilder sb = new ScriptBuilder())
{
sb.EmitSysCall(ApplicationEngine.System_Contract_NativeOnPersist);
Expand Down Expand Up @@ -434,7 +430,7 @@ private void Persist(Block block)
UpdateExtensibleWitnessWhiteList(snapshot);
MemPool.UpdatePoolForBlockPersisted(block, snapshot);
}
block_cache.TryRemove(block.PrevHash, out _);
block_cache.Remove(block.PrevHash);
Context.System.EventStream.Publish(new PersistCompleted { Block = block });
if (HeaderCache.TryRemoveFirst(out Header header))
Debug.Assert(header.Index == block.Index);
Expand Down
92 changes: 35 additions & 57 deletions src/neo/Network/P2P/Payloads/Block.cs
Original file line number Diff line number Diff line change
@@ -1,69 +1,46 @@
using Neo.Cryptography;
using Neo.IO;
using Neo.IO.Json;
using Neo.Persistence;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Neo.Network.P2P.Payloads
{
public class Block : BlockBase, IInventory, IEquatable<Block>
public sealed class Block : IEquatable<Block>, IInventory
{
public const int MaxContentsPerBlock = ushort.MaxValue;
public const int MaxTransactionsPerBlock = MaxContentsPerBlock - 1;
public const int MaxTransactionsPerBlock = ushort.MaxValue;

public ConsensusData ConsensusData;
public Header Header;
public Transaction[] Transactions;

private Header _header = null;
public Header Header
{
get
{
if (_header == null)
{
_header = new Header
{
PrevHash = PrevHash,
MerkleRoot = MerkleRoot,
Timestamp = Timestamp,
Index = Index,
NextConsensus = NextConsensus,
Witness = Witness
};
}
return _header;
}
}
public UInt256 Hash => Header.Hash;
public uint Version => Header.Version;
public UInt256 PrevHash => Header.PrevHash;
public UInt256 MerkleRoot => Header.MerkleRoot;
public ulong Timestamp => Header.Timestamp;
public uint Index => Header.Index;
public byte PrimaryIndex => Header.PrimaryIndex;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This simplifies things a lot, but don't we also want to have a nonce in the header? It might be useful to have for contracts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nonce in the block is an unreliable random number, and contracts should not rely on it.

public UInt160 NextConsensus => Header.NextConsensus;
public Witness Witness => Header.Witness;

InventoryType IInventory.InventoryType => InventoryType.Block;
public int Size => Header.Size + Transactions.GetVarSize();
Witness[] IVerifiable.Witnesses { get => ((IVerifiable)Header).Witnesses; set => throw new NotSupportedException(); }

public override int Size => base.Size
+ IO.Helper.GetVarSize(Transactions.Length + 1) //Count
+ ConsensusData.Size //ConsensusData
+ Transactions.Sum(p => p.Size); //Transactions

public static UInt256 CalculateMerkleRoot(UInt256 consensusDataHash, IEnumerable<UInt256> transactionHashes)
public void Deserialize(BinaryReader reader)
{
return MerkleTree.ComputeRoot(transactionHashes.Prepend(consensusDataHash).ToArray());
}

public override void Deserialize(BinaryReader reader)
{
base.Deserialize(reader);
int count = (int)reader.ReadVarInt(MaxContentsPerBlock);
if (count == 0) throw new FormatException();
ConsensusData = reader.ReadSerializable<ConsensusData>();
Transactions = new Transaction[count - 1];
for (int i = 0; i < Transactions.Length; i++)
Transactions[i] = reader.ReadSerializable<Transaction>();
Header = reader.ReadSerializable<Header>();
Transactions = reader.ReadSerializableArray<Transaction>(MaxTransactionsPerBlock);
if (Transactions.Distinct().Count() != Transactions.Length)
throw new FormatException();
if (CalculateMerkleRoot(ConsensusData.Hash, Transactions.Select(p => p.Hash)) != MerkleRoot)
if (MerkleTree.ComputeRoot(Transactions.Select(p => p.Hash).ToArray()) != Header.MerkleRoot)
throw new FormatException();
}

void IVerifiable.DeserializeUnsigned(BinaryReader reader) => throw new NotSupportedException();

public bool Equals(Block other)
{
if (ReferenceEquals(this, other)) return true;
Expand All @@ -81,26 +58,27 @@ public override int GetHashCode()
return Hash.GetHashCode();
}

public void RebuildMerkleRoot()
{
MerkleRoot = CalculateMerkleRoot(ConsensusData.Hash, Transactions.Select(p => p.Hash));
}
UInt160[] IVerifiable.GetScriptHashesForVerifying(DataCache snapshot) => ((IVerifiable)Header).GetScriptHashesForVerifying(snapshot);

public override void Serialize(BinaryWriter writer)
public void Serialize(BinaryWriter writer)
{
base.Serialize(writer);
writer.WriteVarInt(Transactions.Length + 1);
writer.Write(ConsensusData);
foreach (Transaction tx in Transactions)
writer.Write(tx);
writer.Write(Header);
writer.Write(Transactions);
}

public override JObject ToJson()
void IVerifiable.SerializeUnsigned(BinaryWriter writer) => ((IVerifiable)Header).SerializeUnsigned(writer);

public JObject ToJson()
{
JObject json = base.ToJson();
json["consensusdata"] = ConsensusData.ToJson();
JObject json = Header.ToJson();
json["size"] = Size;
json["tx"] = Transactions.Select(p => p.ToJson()).ToArray();
return json;
}

public bool Verify(DataCache snapshot)
{
return Header.Verify(snapshot);
}
}
}
126 changes: 0 additions & 126 deletions src/neo/Network/P2P/Payloads/BlockBase.cs

This file was deleted.

Loading