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 #1692

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
61 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
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
5 changes: 3 additions & 2 deletions src/neo/Cryptography/MPT/MPTTrie.Proof.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@ private bool GetProof(ref MPTNode node, ReadOnlySpan<byte> path, HashSet<byte[]>

public static TValue VerifyProof(UInt256 root, TKey key, HashSet<byte[]> proof)
{
const byte proof_prefix = 0x00;
shargon marked this conversation as resolved.
Show resolved Hide resolved
using var memoryStore = new MemoryStore();
foreach (byte[] data in proof)
memoryStore.Put(Prefix, Crypto.Hash256(data), data);
memoryStore.Put(proof_prefix, Crypto.Hash256(data), data);
using ISnapshot snapshot = memoryStore.GetSnapshot();
var trie = new MPTTrie<TKey, TValue>(snapshot, root);
var trie = new MPTTrie<TKey, TValue>(snapshot, proof_prefix, root);
return trie[key];
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/neo/Cryptography/MPT/MPTTrie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ public partial class MPTTrie<TKey, TValue>
where TKey : notnull, ISerializable, new()
where TValue : class, ISerializable, new()
{
private const byte Prefix = 0xf0;
private byte Prefix;
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved

private readonly ISnapshot store;
private MPTNode root;

public MPTNode Root => root;

public MPTTrie(ISnapshot store, UInt256 root)
public MPTTrie(ISnapshot store, byte prefix, UInt256 root)
{
this.store = store ?? throw new ArgumentNullException();
this.root = root is null ? HashNode.EmptyNode : new HashNode(root);
this.Prefix = prefix;
this.root = root is null || root == UInt256.Zero ? HashNode.EmptyNode : new HashNode(root);
}

private MPTNode Resolve(HashNode n)
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
}
}
126 changes: 126 additions & 0 deletions src/neo/Network/P2P/Payloads/StateRoot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
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;
return script_hash is null ? Array.Empty<UInt160>() : new UInt160[] { script_hash };
}

public byte[] GetMessage()
{
return this.GetHashData();
}

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
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, byte prefix, UInt256 root)
{
mptTrie = new MPTTrie<TKey, TValue>(store as ISnapshot, prefix, 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);
}
}
}
2 changes: 2 additions & 0 deletions src/neo/Persistence/Prefixes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ internal static class Prefixes

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, Prefixes.ST_Storage, 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
11 changes: 10 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,16 +30,22 @@ 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, Prefixes.ST_Storage, CurrentStateRootHash);//Need BlockHashIndex and LocalStateRoot loaded.
}

public override void Commit()
{
base.Commit();
var root = LocalStateRoot.GetAndChange(Height, () => new HashIndexState());
root.Index = Height;
root.Hash = ((MPTDataCache<StorageKey, StorageItem>)Storages).Root.Hash;
Copy link
Contributor

Choose a reason for hiding this comment

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

Move it to blockchain.cs

LocalStateRoot.Commit();
snapshot.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
Loading