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

[neox] persistence #1721

Merged
merged 62 commits into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
3f083d2
Merge pull request #1 from neo-project/master
ZhangTao1596 Jan 20, 2020
05aaade
Merge pull request #2 from neo-project/master
ZhangTao1596 Feb 4, 2020
39da07b
Merge pull request #5 from neo-project/master
ZhangTao1596 Feb 12, 2020
caa9426
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Mar 24, 2020
aa06d4c
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Apr 23, 2020
144d8d1
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Jun 1, 2020
71dc2e8
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Jun 2, 2020
62d34b3
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Jun 4, 2020
f114093
don't use snapshot directly in plugin
ZhangTao1596 Jun 5, 2020
b85d68e
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Jun 8, 2020
a8faab8
persistence and ut
ZhangTao1596 Jun 8, 2020
294e9b9
fix mpt
ZhangTao1596 Jun 8, 2020
bc945a5
precommit
ZhangTao1596 Jun 9, 2020
6ef3ccb
fix commit
ZhangTao1596 Jun 9, 2020
e5cdb62
Merge branch 'neox-persistence' of github.com:KickSeason/neo into neo…
ZhangTao1596 Jun 9, 2020
2cd85d0
rm LocalRootHashIndex
ZhangTao1596 Jun 9, 2020
cfccec9
fix ut
ZhangTao1596 Jun 10, 2020
ef8c14c
pre commit
ZhangTao1596 Jun 10, 2020
d2cc98d
fix clone view
ZhangTao1596 Jun 10, 2020
559831e
change name
ZhangTao1596 Jun 10, 2020
88eeff2
rename
ZhangTao1596 Jun 10, 2020
f97c15a
abstract
ZhangTao1596 Jun 10, 2020
2b20fc8
comment
ZhangTao1596 Jun 11, 2020
1fd6136
fix ReadOnlyView
ZhangTao1596 Jun 11, 2020
4b818a2
rm precommit
ZhangTao1596 Jun 11, 2020
0c07d4b
rm HashState
ZhangTao1596 Jun 11, 2020
fcefc80
add MPTDataCache
Jun 11, 2020
45505c9
optimze
Jun 11, 2020
d9c5ee2
optimize
Jun 11, 2020
550c72e
remove blank line
Jun 11, 2020
5b6924f
StateRoot verify fee
ZhangTao1596 Jun 12, 2020
9e98192
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 12, 2020
fb09bb0
expose Root in MPTDataCache
ZhangTao1596 Jun 12, 2020
7172da6
Merge branch 'neox-persistence' of github.com:KickSeason/neo into neo…
ZhangTao1596 Jun 12, 2020
b197725
fix some and ut
ZhangTao1596 Jun 12, 2020
586e751
Merge branch 'master' into neox-persistence
Jun 12, 2020
b81db5b
Merge branch 'master' of github.com:neo-project/neo
ZhangTao1596 Jun 12, 2020
e69cdab
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 12, 2020
2376eb2
merge master
ZhangTao1596 Jun 12, 2020
a42998f
master
ZhangTao1596 Jun 12, 2020
10f2f3c
fix mpt ut
ZhangTao1596 Jun 12, 2020
b1b5f12
Merge branch 'neox-persistence' of github.com:KickSeason/neo into neo…
ZhangTao1596 Jun 12, 2020
fae1d14
fix Storages and name
ZhangTao1596 Jun 12, 2020
520d03b
rename
ZhangTao1596 Jun 12, 2020
80235bc
add comment
ZhangTao1596 Jun 12, 2020
a3b491d
proof prefix
ZhangTao1596 Jun 12, 2020
aeff67c
fix
ZhangTao1596 Jun 12, 2020
1337cd7
format
ZhangTao1596 Jun 12, 2020
17b67e6
format
ZhangTao1596 Jun 12, 2020
b018556
format
ZhangTao1596 Jun 12, 2020
404185a
add StateRoot ut
ZhangTao1596 Jun 12, 2020
2acfacf
reset mpt prefix
Jun 13, 2020
0d7490a
rm GetMessage
ZhangTao1596 Jun 15, 2020
d68ba68
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 16, 2020
59c8706
throw exception when no script hash in state root
ZhangTao1596 Jun 16, 2020
ac6a24b
UpdateLocalStateRoot when Storages changed
ZhangTao1596 Jun 16, 2020
924a6d6
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 18, 2020
00e9d9f
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 18, 2020
6fe285a
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 19, 2020
e56c433
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 20, 2020
26aa1de
Merge branch 'master' into neox-persistence
ZhangTao1596 Jun 22, 2020
fa91cde
rename
ZhangTao1596 Jun 28, 2020
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
2 changes: 1 addition & 1 deletion src/neo/Cryptography/MPT/MPTTrie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public partial class MPTTrie<TKey, TValue>
public MPTTrie(ISnapshot store, UInt256 root)
{
this.store = store ?? throw new ArgumentNullException();
this.root = root is null ? HashNode.EmptyNode : new HashNode(root);
this.root = root is null || root == UInt256.Zero ? HashNode.EmptyNode : new HashNode(root);
}

private MPTNode Resolve(HashNode n)
Expand Down
1 change: 1 addition & 0 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ private void Persist(Block block)
snapshot.BlockHashIndex.GetAndChange().Set(block);
foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins)
plugin.OnPersist(snapshot, all_application_executed);
snapshot.UpdateLocalStateRoot();
snapshot.Commit();
List<Exception> commitExceptions = null;
foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins)
Expand Down
2 changes: 2 additions & 0 deletions src/neo/Network/P2P/MessageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public enum MessageCommand : byte
Block = 0x2c,
[ReflectionCache(typeof(ConsensusPayload))]
Consensus = 0x2d,
[ReflectionCache(typeof(StateRoot))]
StateRoot = 0x2e,
Reject = 0x2f,

//SPV protocol
Expand Down
1 change: 1 addition & 0 deletions src/neo/Network/P2P/Payloads/InventoryType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public enum InventoryType : byte
{
TX = MessageCommand.Transaction,
Block = MessageCommand.Block,
StateRoot = MessageCommand.StateRoot,
Consensus = MessageCommand.Consensus
}
}
122 changes: 122 additions & 0 deletions src/neo/Network/P2P/Payloads/StateRoot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using Neo.Cryptography;
using Neo.IO;
using Neo.IO.Json;
using Neo.Ledger;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using System;
using System.IO;

namespace Neo.Network.P2P.Payloads
{
public class StateRoot : ICloneable<StateRoot>, IInventory
{
public byte Version;
public uint Index;
public UInt256 Root;
public Witness Witness;

InventoryType IInventory.InventoryType => InventoryType.StateRoot;

private UInt256 _hash = null;

public UInt256 Hash
{
get
{
if (_hash == null)
{
_hash = new UInt256(Crypto.Hash256(this.GetHashData()));
}
return _hash;
}
}

Witness[] IVerifiable.Witnesses
{
get
{
return new[] { Witness };
}
set
{
if (value.Length != 1) throw new ArgumentException();
Witness = value[0];
}
}

public int Size =>
sizeof(byte) + //Version
sizeof(uint) + //Index
UInt256.Length + //Root
Witness.Size; //Witness

StateRoot ICloneable<StateRoot>.Clone()
{
return new StateRoot
{
Version = Version,
Index = Index,
Root = Root,
Witness = Witness,
};
}

void ICloneable<StateRoot>.FromReplica(StateRoot replica)
{
Version = replica.Version;
Index = replica.Index;
Root = replica.Root;
Witness = replica.Witness;
}

public void Deserialize(BinaryReader reader)
{
this.DeserializeUnsigned(reader);
Witness = reader.ReadSerializable<Witness>();
}

public void DeserializeUnsigned(BinaryReader reader)
{
Version = reader.ReadByte();
Index = reader.ReadUInt32();
Root = reader.ReadSerializable<UInt256>();
}

public void Serialize(BinaryWriter writer)
{
this.SerializeUnsigned(writer);
writer.Write(Witness);
}

public void SerializeUnsigned(BinaryWriter writer)
{
writer.Write(Version);
writer.Write(Index);
writer.Write(Root);
}

public bool Verify(StoreView snapshot)
{
return this.VerifyWitnesses(snapshot, 1_00000000);
}

public virtual UInt160[] GetScriptHashesForVerifying(StoreView snapshot)
{
var script_hash = Blockchain.Singleton.GetBlock(Index)?.NextConsensus;
if (script_hash is null) throw new System.InvalidOperationException("No script hash for state root verifying");
return new UInt160[] { script_hash };
}

public JObject ToJson()
{
var json = new JObject();
json["version"] = Version;
json["index"] = Index;
json["stateroot"] = Root.ToString();
json["witness"] = Witness.ToJson();
return json;
}
}
}
6 changes: 6 additions & 0 deletions src/neo/Persistence/ClonedView.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Neo.Cryptography.MPT;
using Neo.IO;
using Neo.IO.Caching;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;

namespace Neo.Persistence
{
Expand All @@ -11,8 +13,10 @@ internal class ClonedView : StoreView
public override DataCache<UInt160, ContractState> Contracts { get; }
public override DataCache<StorageKey, StorageItem> Storages { get; }
public override DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList { get; }
public override DataCache<SerializableWrapper<uint>, HashIndexState> LocalStateRoot { get; }
public override MetaDataCache<HashIndexState> BlockHashIndex { get; }
public override MetaDataCache<HashIndexState> HeaderHashIndex { get; }
public override MetaDataCache<StateRoot> ValidatorsStateRoot { get; }
public override MetaDataCache<ContractIdState> ContractId { get; }

public ClonedView(StoreView view)
Expand All @@ -23,8 +27,10 @@ public ClonedView(StoreView view)
this.Contracts = view.Contracts.CreateSnapshot();
this.Storages = view.Storages.CreateSnapshot();
this.HeaderHashList = view.HeaderHashList.CreateSnapshot();
this.LocalStateRoot = view.LocalStateRoot.CreateSnapshot();
this.BlockHashIndex = view.BlockHashIndex.CreateSnapshot();
this.HeaderHashIndex = view.HeaderHashIndex.CreateSnapshot();
this.ValidatorsStateRoot = view.ValidatorsStateRoot.CreateSnapshot();
this.ContractId = view.ContractId.CreateSnapshot();
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/neo/Persistence/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Neo.Ledger;

namespace Neo.Persistence
{
Expand All @@ -8,5 +9,13 @@ public static byte[] EnsureNotNull(this byte[] source)
{
return source ?? Array.Empty<byte>();
}

public static void UpdateLocalStateRoot(this SnapshotView snapshot)
{
snapshot.Storages.Commit();
var root = snapshot.LocalStateRoot.GetAndChange(snapshot.Height, () => new HashIndexState());
root.Index = snapshot.Height;
root.Hash = ((MPTDataCache<StorageKey, StorageItem>)snapshot.Storages).Root.Hash;
}
}
}
53 changes: 53 additions & 0 deletions src/neo/Persistence/MPTDataCache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

using Neo.Cryptography.MPT;
using Neo.IO;
using Neo.IO.Caching;
using System;
using System.Collections.Generic;

namespace Neo.Persistence
{
internal class MPTDataCache<TKey, TValue> : DataCache<TKey, TValue>
where TKey : IEquatable<TKey>, ISerializable, new()
where TValue : class, ICloneable<TValue>, ISerializable, new()
{
private MPTTrie<TKey, TValue> mptTrie;

public MPTNode Root => mptTrie.Root;

public MPTDataCache(IReadOnlyStore store, UInt256 root)
{
mptTrie = new MPTTrie<TKey, TValue>(store as ISnapshot, root);
}

protected override void AddInternal(TKey key, TValue value)
{
mptTrie.Put(key, value);
}

protected override void DeleteInternal(TKey key)
{
mptTrie.Delete(key);
}

protected override IEnumerable<(TKey Key, TValue Value)> FindInternal(byte[] key_prefix)
{
return mptTrie.Find(key_prefix);
}

protected override TValue GetInternal(TKey key)
{
return mptTrie[key];
}

protected override TValue TryGetInternal(TKey key)
{
return mptTrie[key];
}

protected override void UpdateInternal(TKey key, TValue value)
{
mptTrie.Put(key, value);
}
}
}
3 changes: 2 additions & 1 deletion src/neo/Persistence/Prefixes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ internal static class Prefixes
public const byte DATA_Transaction = 0x02;

public const byte ST_Contract = 0x50;
public const byte ST_Storage = 0x70;
public const byte ST_LocalStateRoot = 0x60;

public const byte IX_HeaderHashList = 0x80;
public const byte IX_CurrentBlock = 0xc0;
public const byte IX_CurrentHeader = 0xc1;
public const byte IX_ContractId = 0xc2;
public const byte IX_ValidatorsStateRoot = 0xc4;

/* Prefixes 0xf0 to 0xff are reserved for external use.
*
Expand Down
6 changes: 5 additions & 1 deletion src/neo/Persistence/ReadOnlyView.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Neo.Cryptography.MPT;
using Neo.IO;
using Neo.IO.Caching;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using System;

namespace Neo.Persistence
Expand All @@ -15,10 +17,12 @@ public class ReadOnlyView : StoreView
public override DataCache<UInt256, TrimmedBlock> Blocks => new StoreDataCache<UInt256, TrimmedBlock>(store, Prefixes.DATA_Block);
public override DataCache<UInt256, TransactionState> Transactions => new StoreDataCache<UInt256, TransactionState>(store, Prefixes.DATA_Transaction);
public override DataCache<UInt160, ContractState> Contracts => new StoreDataCache<UInt160, ContractState>(store, Prefixes.ST_Contract);
public override DataCache<StorageKey, StorageItem> Storages => new StoreDataCache<StorageKey, StorageItem>(store, Prefixes.ST_Storage);
public override DataCache<StorageKey, StorageItem> Storages => new MPTDataCache<StorageKey, StorageItem>(store, CurrentStateRootHash);
public override DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList => new StoreDataCache<SerializableWrapper<uint>, HeaderHashList>(store, Prefixes.IX_HeaderHashList);
public override DataCache<SerializableWrapper<uint>, HashIndexState> LocalStateRoot => new StoreDataCache<SerializableWrapper<uint>, HashIndexState>(store, Prefixes.ST_LocalStateRoot);
public override MetaDataCache<HashIndexState> BlockHashIndex => new StoreMetaDataCache<HashIndexState>(store, Prefixes.IX_CurrentBlock);
public override MetaDataCache<HashIndexState> HeaderHashIndex => new StoreMetaDataCache<HashIndexState>(store, Prefixes.IX_CurrentHeader);
public override MetaDataCache<StateRoot> ValidatorsStateRoot => new StoreMetaDataCache<StateRoot>(store, Prefixes.IX_ValidatorsStateRoot);
public override MetaDataCache<ContractIdState> ContractId => new StoreMetaDataCache<ContractIdState>(store, Prefixes.IX_ContractId);

public ReadOnlyView(IReadOnlyStore store)
Expand Down
7 changes: 6 additions & 1 deletion src/neo/Persistence/SnapshotView.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Neo.IO;
using Neo.IO.Caching;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using System;

namespace Neo.Persistence
Expand All @@ -17,8 +18,10 @@ public class SnapshotView : StoreView, IDisposable
public override DataCache<UInt160, ContractState> Contracts { get; }
public override DataCache<StorageKey, StorageItem> Storages { get; }
public override DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList { get; }
public override DataCache<SerializableWrapper<uint>, HashIndexState> LocalStateRoot { get; }
public override MetaDataCache<HashIndexState> BlockHashIndex { get; }
public override MetaDataCache<HashIndexState> HeaderHashIndex { get; }
public override MetaDataCache<StateRoot> ValidatorsStateRoot { get; }
public override MetaDataCache<ContractIdState> ContractId { get; }

public SnapshotView(IStore store)
Expand All @@ -27,11 +30,13 @@ public SnapshotView(IStore store)
Blocks = new StoreDataCache<UInt256, TrimmedBlock>(snapshot, Prefixes.DATA_Block);
Transactions = new StoreDataCache<UInt256, TransactionState>(snapshot, Prefixes.DATA_Transaction);
Contracts = new StoreDataCache<UInt160, ContractState>(snapshot, Prefixes.ST_Contract);
Storages = new StoreDataCache<StorageKey, StorageItem>(snapshot, Prefixes.ST_Storage);
HeaderHashList = new StoreDataCache<SerializableWrapper<uint>, HeaderHashList>(snapshot, Prefixes.IX_HeaderHashList);
LocalStateRoot = new StoreDataCache<SerializableWrapper<uint>, HashIndexState>(snapshot, Prefixes.ST_LocalStateRoot);
BlockHashIndex = new StoreMetaDataCache<HashIndexState>(snapshot, Prefixes.IX_CurrentBlock);
HeaderHashIndex = new StoreMetaDataCache<HashIndexState>(snapshot, Prefixes.IX_CurrentHeader);
ContractId = new StoreMetaDataCache<ContractIdState>(snapshot, Prefixes.IX_ContractId);
ValidatorsStateRoot = new StoreMetaDataCache<StateRoot>(snapshot, Prefixes.IX_ValidatorsStateRoot);
Storages = new MPTDataCache<StorageKey, StorageItem>(snapshot, CurrentStateRootHash);//Need BlockHashIndex and LocalStateRoot loaded.
}

public override void Commit()
Expand Down
5 changes: 5 additions & 0 deletions src/neo/Persistence/StoreView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ public abstract class StoreView
public abstract DataCache<UInt160, ContractState> Contracts { get; }
public abstract DataCache<StorageKey, StorageItem> Storages { get; }
public abstract DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList { get; }
public abstract DataCache<SerializableWrapper<uint>, HashIndexState> LocalStateRoot { get; }
public abstract MetaDataCache<HashIndexState> BlockHashIndex { get; }
public abstract MetaDataCache<HashIndexState> HeaderHashIndex { get; }
public abstract MetaDataCache<StateRoot> ValidatorsStateRoot { get; }
public abstract MetaDataCache<ContractIdState> ContractId { get; }

public uint Height => BlockHashIndex.Get().Index;
public uint HeaderHeight => HeaderHashIndex.Get().Index;
public UInt256 CurrentBlockHash => BlockHashIndex.Get().Hash;
public UInt256 CurrentStateRootHash => LocalStateRoot.TryGet(Height)?.Hash ?? UInt256.Zero;
public UInt256 CurrentHeaderHash => HeaderHashIndex.Get().Hash;

public StoreView Clone()
Expand All @@ -37,9 +40,11 @@ public virtual void Commit()
Contracts.Commit();
Storages.Commit();
HeaderHashList.Commit();
LocalStateRoot.Commit();
BlockHashIndex.Commit();
HeaderHashIndex.Commit();
ContractId.Commit();
ValidatorsStateRoot.Commit();
}

public bool ContainsBlock(UInt256 hash)
Expand Down
3 changes: 3 additions & 0 deletions tests/neo.UnitTests/Consensus/UT_Consensus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Neo.Ledger;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.UnitTests.Cryptography;
Expand Down Expand Up @@ -276,6 +277,7 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm
{
Value = mockContext.Object.Validators.ToByteArray()
});
mockContext.Object.Snapshot.UpdateLocalStateRoot();
mockContext.Object.Snapshot.Commit();
// ===============================================================

Expand Down Expand Up @@ -408,6 +410,7 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm
Console.WriteLine("mockContext Reset for returning Blockchain.Singleton snapshot to original state.");
mockContext.Object.Reset(0);
mockContext.Object.Snapshot.Storages.Delete(CreateStorageKeyForNativeNeo(14));
mockContext.Object.Snapshot.UpdateLocalStateRoot();
mockContext.Object.Snapshot.Commit();

Console.WriteLine("mockContext Reset.");
Expand Down
Loading