diff --git a/src/neo/IO/Caching/CloneCache.cs b/src/neo/IO/Caching/CloneCache.cs deleted file mode 100644 index 45da3cc7da..0000000000 --- a/src/neo/IO/Caching/CloneCache.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Neo.IO.Caching -{ - internal class CloneCache : DataCache - where TKey : IEquatable, ISerializable - where TValue : class, ICloneable, ISerializable, new() - { - private readonly DataCache innerCache; - - public CloneCache(DataCache innerCache) - { - this.innerCache = innerCache; - } - - protected override void AddInternal(TKey key, TValue value) - { - innerCache.Add(key, value); - } - - protected override void DeleteInternal(TKey key) - { - innerCache.Delete(key); - } - - protected override bool ContainsInternal(TKey key) - { - return innerCache.Contains(key); - } - - protected override TValue GetInternal(TKey key) - { - return innerCache[key].Clone(); - } - - protected override IEnumerable<(TKey, TValue)> SeekInternal(byte[] keyOrPreifx, SeekDirection direction) - { - foreach (var (key, value) in innerCache.Seek(keyOrPreifx, direction)) - yield return (key, value.Clone()); - } - - protected override TValue TryGetInternal(TKey key) - { - return innerCache.TryGet(key)?.Clone(); - } - - protected override void UpdateInternal(TKey key, TValue value) - { - innerCache.GetAndChange(key).FromReplica(value); - } - } -} diff --git a/src/neo/IO/Caching/CloneMetaCache.cs b/src/neo/IO/Caching/CloneMetaCache.cs deleted file mode 100644 index 3cb0d83201..0000000000 --- a/src/neo/IO/Caching/CloneMetaCache.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Neo.IO.Caching -{ - internal class CloneMetaCache : MetaDataCache - where T : class, ICloneable, ISerializable, new() - { - private readonly MetaDataCache innerCache; - - public CloneMetaCache(MetaDataCache innerCache) - : base(null) - { - this.innerCache = innerCache; - } - - protected override void AddInternal(T item) - { - } - - protected override T TryGetInternal() - { - return innerCache.Get().Clone(); - } - - protected override void UpdateInternal(T item) - { - innerCache.GetAndChange().FromReplica(item); - } - } -} diff --git a/src/neo/IO/Caching/MetaDataCache.cs b/src/neo/IO/Caching/MetaDataCache.cs deleted file mode 100644 index f0c40cc59a..0000000000 --- a/src/neo/IO/Caching/MetaDataCache.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; - -namespace Neo.IO.Caching -{ - public abstract class MetaDataCache - where T : class, ICloneable, ISerializable, new() - { - private T Item; - private TrackState State; - private readonly Func factory; - - protected abstract void AddInternal(T item); - protected abstract T TryGetInternal(); - protected abstract void UpdateInternal(T item); - - protected MetaDataCache(Func factory) - { - this.factory = factory; - } - - public void Commit() - { - switch (State) - { - case TrackState.Added: - AddInternal(Item); - break; - case TrackState.Changed: - UpdateInternal(Item); - break; - } - } - - public MetaDataCache CreateSnapshot() - { - return new CloneMetaCache(this); - } - - public T Get() - { - if (Item == null) - { - Item = TryGetInternal(); - } - if (Item == null) - { - Item = factory?.Invoke() ?? new T(); - State = TrackState.Added; - } - return Item; - } - - public T GetAndChange() - { - T item = Get(); - if (State == TrackState.None) - State = TrackState.Changed; - return item; - } - } -} diff --git a/src/neo/IO/ICloneable.cs b/src/neo/IO/ICloneable.cs deleted file mode 100644 index 83b4d77725..0000000000 --- a/src/neo/IO/ICloneable.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Neo.IO -{ - public interface ICloneable - { - T Clone(); - void FromReplica(T replica); - } -} diff --git a/src/neo/IO/SerializableWrapper.cs b/src/neo/IO/SerializableWrapper.cs deleted file mode 100644 index 5533a44171..0000000000 --- a/src/neo/IO/SerializableWrapper.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.IO; - -namespace Neo.IO -{ - public class SerializableWrapper : IEquatable, IEquatable>, ISerializable - where T : unmanaged - { - private static unsafe readonly int ValueSize = sizeof(T); - private T value; - - public SerializableWrapper() - { - } - - private SerializableWrapper(T value) - { - this.value = value; - } - - public int Size => ValueSize; - - public unsafe void Deserialize(BinaryReader reader) - { - fixed (T* p = &value) - { - Span buffer = new Span(p, ValueSize); - int i = 0; - while (i < ValueSize) - { - int count = reader.Read(buffer[i..]); - if (count == 0) throw new FormatException(); - i += count; - } - } - } - - public bool Equals(T other) - { - return value.Equals(other); - } - - public bool Equals(SerializableWrapper other) - { - return value.Equals(other.value); - } - - public unsafe void Serialize(BinaryWriter writer) - { - fixed (T* p = &value) - { - ReadOnlySpan buffer = new ReadOnlySpan(p, ValueSize); - writer.Write(buffer); - } - } - - public static implicit operator SerializableWrapper(T value) - { - return new SerializableWrapper(value); - } - - public static implicit operator T(SerializableWrapper wrapper) - { - return wrapper.value; - } - } -} diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index bf26f6c70d..e7bb4bcfba 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -43,7 +43,7 @@ public class RelayResult { public IInventory Inventory; public VerifyResult Resu PrevHash = UInt256.Zero, Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestampMS(), Index = 0, - NextConsensus = GetConsensusAddress(StandbyValidators), + NextConsensus = Contract.GetBFTAddress(StandbyValidators), Witness = new Witness { InvocationScript = Array.Empty(), @@ -62,21 +62,17 @@ 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 List header_index = new List(); - private uint stored_header_count = 0; private readonly ConcurrentDictionary block_cache = new ConcurrentDictionary(); private readonly Dictionary block_cache_unverified = new Dictionary(); internal readonly RelayCache RelayCache = new RelayCache(100); - private SnapshotView currentSnapshot; + private SnapshotCache currentSnapshot; private ImmutableHashSet extensibleWitnessWhiteList; public IStore Store { get; } - public ReadOnlyView View { get; } + public DataCache View => new SnapshotCache(Store); public MemoryPool MemPool { get; } - public uint Height => currentSnapshot.Height; - public uint HeaderHeight => currentSnapshot.HeaderHeight; - public UInt256 CurrentBlockHash => currentSnapshot.CurrentBlockHash; - public UInt256 CurrentHeaderHash => currentSnapshot.CurrentHeaderHash; + public uint Height => NativeContract.Ledger.CurrentIndex(currentSnapshot); + public UInt256 CurrentBlockHash => NativeContract.Ledger.CurrentHash(currentSnapshot); private static Blockchain singleton; public static Blockchain Singleton @@ -110,31 +106,11 @@ public Blockchain(NeoSystem system, IStore store) this.txrouter = Context.ActorOf(TransactionRouter.Props(system)); this.MemPool = new MemoryPool(system, ProtocolSettings.Default.MemoryPoolMaxTransactions); this.Store = store; - this.View = new ReadOnlyView(store); lock (lockObj) { if (singleton != null) throw new InvalidOperationException(); - header_index.AddRange(View.HeaderHashList.Find().OrderBy(p => (uint)p.Key).SelectMany(p => p.Value.Hashes)); - stored_header_count += (uint)header_index.Count; - if (stored_header_count == 0) - { - header_index.AddRange(View.Blocks.Find().OrderBy(p => p.Value.Index).Select(p => p.Key)); - } - else - { - HashIndexState hashIndex = View.HeaderHashIndex.Get(); - if (hashIndex.Index >= stored_header_count) - { - DataCache cache = View.Blocks; - for (UInt256 hash = hashIndex.Hash; hash != header_index[(int)stored_header_count - 1];) - { - header_index.Insert((int)stored_header_count, hash); - hash = cache[hash].PrevHash; - } - } - } - if (header_index.Count == 0) + if (!NativeContract.Ledger.Initialized(View)) { Persist(GenesisBlock); } @@ -147,76 +123,15 @@ public Blockchain(NeoSystem system, IStore store) } } - public bool ContainsBlock(UInt256 hash) - { - if (block_cache.ContainsKey(hash)) return true; - return View.ContainsBlock(hash); - } - - public bool ContainsTransaction(UInt256 hash) + private bool ContainsTransaction(UInt256 hash) { if (MemPool.ContainsKey(hash)) return true; - return View.ContainsTransaction(hash); - } - - public Block GetBlock(uint index) - { - if (index == 0) return GenesisBlock; - UInt256 hash = GetBlockHash(index); - if (hash == null) return null; - return GetBlock(hash); + return NativeContract.Ledger.ContainsTransaction(View, hash); } - public Block GetBlock(UInt256 hash) + public SnapshotCache GetSnapshot() { - if (block_cache.TryGetValue(hash, out Block block)) - return block; - return View.GetBlock(hash); - } - - public UInt256 GetBlockHash(uint index) - { - if (header_index.Count <= index) return null; - return header_index[(int)index]; - } - - public static UInt160 GetConsensusAddress(ECPoint[] validators) - { - return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); - } - - public Header GetHeader(uint index) - { - if (index == 0) return GenesisBlock.Header; - UInt256 hash = GetBlockHash(index); - if (hash == null) return null; - return GetHeader(hash); - } - - public Header GetHeader(UInt256 hash) - { - if (block_cache.TryGetValue(hash, out Block block)) - return block.Header; - return View.GetHeader(hash); - } - - public UInt256 GetNextBlockHash(UInt256 hash) - { - Header header = GetHeader(hash); - if (header == null) return null; - return GetBlockHash(header.Index + 1); - } - - public SnapshotView GetSnapshot() - { - return new SnapshotView(Store); - } - - public Transaction GetTransaction(UInt256 hash) - { - if (MemPool.TryGetValue(hash, out Transaction transaction)) - return transaction; - return View.GetTransaction(hash); + return new SnapshotCache(Store.GetSnapshot()); } private void OnImport(IEnumerable blocks, bool verify) @@ -229,7 +144,6 @@ private void OnImport(IEnumerable blocks, bool verify) if (verify && !block.Verify(currentSnapshot)) throw new InvalidOperationException(); Persist(block); - SaveHeaderHashList(); } Sender.Tell(new ImportCompleted()); } @@ -271,7 +185,7 @@ private void OnFillMemoryPool(IEnumerable transactions) // Add the transactions to the memory pool foreach (var tx in transactions) { - if (View.ContainsTransaction(tx.Hash)) + if (NativeContract.Ledger.ContainsTransaction(View, tx.Hash)) continue; // First remove the tx if it is unverified in the pool. MemPool.TryRemoveUnVerified(tx.Hash, out _); @@ -314,7 +228,6 @@ private VerifyResult OnNewBlock(Block block) block_cache.TryAdd(block.Hash, block); block_cache_unverified.Remove(block.Index); Persist(block); - SaveHeaderHashList(); if (block_cache_unverified.TryGetValue(Height + 1, out var unverifiedBlocks)) { foreach (var unverifiedBlock in unverifiedBlocks.Blocks) @@ -387,13 +300,8 @@ private void OnTransaction(Transaction tx) private void Persist(Block block) { - using (SnapshotView snapshot = GetSnapshot()) + using (SnapshotCache snapshot = GetSnapshot()) { - if (block.Index == header_index.Count) - { - header_index.Add(block.Hash); - snapshot.HeaderHashIndex.GetAndChange().Set(block); - } List all_application_executed = new List(); using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, block)) { @@ -403,38 +311,26 @@ private void Persist(Block block) Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } - snapshot.Blocks.Add(block.Hash, block.Trim()); - StoreView clonedSnapshot = snapshot.Clone(); + DataCache clonedSnapshot = snapshot.CreateSnapshot(); // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (Transaction tx in block.Transactions) { - var state = new TransactionState - { - BlockIndex = block.Index, - Transaction = tx - }; - - clonedSnapshot.Transactions.Add(tx.Hash, state); - clonedSnapshot.Transactions.Commit(); - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, block, tx.SystemFee)) { engine.LoadScript(tx.Script); - state.VMState = engine.Execute(); - if (state.VMState == VMState.HALT) + if (engine.Execute() == VMState.HALT) { clonedSnapshot.Commit(); } else { - clonedSnapshot = snapshot.Clone(); + clonedSnapshot = snapshot.CreateSnapshot(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } - snapshot.BlockHashIndex.GetAndChange().Set(block); using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.PostPersist, null, snapshot, block)) { engine.LoadScript(postPersistScript); @@ -483,30 +379,6 @@ public static Props Props(NeoSystem system, IStore store) return Akka.Actor.Props.Create(() => new Blockchain(system, store)).WithMailbox("blockchain-mailbox"); } - private void SaveHeaderHashList(SnapshotView snapshot = null) - { - if ((header_index.Count - stored_header_count < 2000)) - return; - bool snapshot_created = snapshot == null; - if (snapshot_created) snapshot = GetSnapshot(); - try - { - while (header_index.Count - stored_header_count >= 2000) - { - snapshot.HeaderHashList.Add(stored_header_count, new HeaderHashList - { - Hashes = header_index.Skip((int)stored_header_count).Take(2000).ToArray() - }); - stored_header_count += 2000; - } - if (snapshot_created) snapshot.Commit(); - } - finally - { - if (snapshot_created) snapshot.Dispose(); - } - } - private void SendRelayResult(IInventory inventory, VerifyResult result) { RelayResult rr = new RelayResult @@ -524,18 +396,18 @@ private void UpdateCurrentSnapshot() var builder = ImmutableHashSet.CreateBuilder(); builder.Add(NativeContract.NEO.GetCommitteeAddress(currentSnapshot)); var validators = NativeContract.NEO.GetNextBlockValidators(currentSnapshot); - builder.Add(GetConsensusAddress(validators)); + builder.Add(Contract.GetBFTAddress(validators)); builder.UnionWith(validators.Select(u => Contract.CreateSignatureRedeemScript(u).ToScriptHash())); - var oracles = NativeContract.RoleManagement.GetDesignatedByRole(currentSnapshot, Role.Oracle, currentSnapshot.Height); + var oracles = NativeContract.RoleManagement.GetDesignatedByRole(currentSnapshot, Role.Oracle, Height); if (oracles.Length > 0) { - builder.Add(GetConsensusAddress(oracles)); + builder.Add(Contract.GetBFTAddress(oracles)); builder.UnionWith(oracles.Select(u => Contract.CreateSignatureRedeemScript(u).ToScriptHash())); } - var stateValidators = NativeContract.RoleManagement.GetDesignatedByRole(currentSnapshot, Role.StateValidator, currentSnapshot.Height); + var stateValidators = NativeContract.RoleManagement.GetDesignatedByRole(currentSnapshot, Role.StateValidator, Height); if (stateValidators.Length > 0) { - builder.Add(GetConsensusAddress(stateValidators)); + builder.Add(Contract.GetBFTAddress(stateValidators)); builder.UnionWith(stateValidators.Select(u => Contract.CreateSignatureRedeemScript(u).ToScriptHash())); } extensibleWitnessWhiteList = builder.ToImmutable(); diff --git a/src/neo/Ledger/HashIndexState.cs b/src/neo/Ledger/HashIndexState.cs deleted file mode 100644 index fb7439a252..0000000000 --- a/src/neo/Ledger/HashIndexState.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Neo.IO; -using Neo.Network.P2P.Payloads; -using System.IO; - -namespace Neo.Ledger -{ - public class HashIndexState : ICloneable, ISerializable - { - public UInt256 Hash = UInt256.Zero; - public uint Index = uint.MaxValue; - - int ISerializable.Size => Hash.Size + sizeof(uint); - - HashIndexState ICloneable.Clone() - { - return new HashIndexState - { - Hash = Hash, - Index = Index - }; - } - - void ISerializable.Deserialize(BinaryReader reader) - { - Hash = reader.ReadSerializable(); - Index = reader.ReadUInt32(); - } - - void ICloneable.FromReplica(HashIndexState replica) - { - Hash = replica.Hash; - Index = replica.Index; - } - - void ISerializable.Serialize(BinaryWriter writer) - { - writer.Write(Hash); - writer.Write(Index); - } - - internal void Set(BlockBase block) - { - Hash = block.Hash; - Index = block.Index; - } - } -} diff --git a/src/neo/Ledger/HeaderHashList.cs b/src/neo/Ledger/HeaderHashList.cs deleted file mode 100644 index 928a26e5d2..0000000000 --- a/src/neo/Ledger/HeaderHashList.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Neo.IO; -using System.IO; - -namespace Neo.Ledger -{ - public class HeaderHashList : ICloneable, ISerializable - { - public UInt256[] Hashes; - - int ISerializable.Size => Hashes.GetVarSize(); - - HeaderHashList ICloneable.Clone() - { - return new HeaderHashList - { - Hashes = Hashes - }; - } - - void ISerializable.Deserialize(BinaryReader reader) - { - Hashes = reader.ReadSerializableArray(); - } - - void ICloneable.FromReplica(HeaderHashList replica) - { - Hashes = replica.Hashes; - } - - void ISerializable.Serialize(BinaryWriter writer) - { - writer.Write(Hashes); - } - } -} diff --git a/src/neo/Ledger/MemoryPool.cs b/src/neo/Ledger/MemoryPool.cs index 74697d041f..bc15638fef 100644 --- a/src/neo/Ledger/MemoryPool.cs +++ b/src/neo/Ledger/MemoryPool.cs @@ -1,4 +1,3 @@ -using Akka.Actor; using Akka.Util.Internal; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; @@ -104,7 +103,7 @@ public MemoryPool(NeoSystem system, int capacity) Capacity = capacity; } - internal void LoadPolicy(StoreView snapshot) + internal void LoadPolicy(DataCache snapshot) { _maxTxPerBlock = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(snapshot); } @@ -206,7 +205,7 @@ public IEnumerable GetSortedVerifiedTransactions() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private PoolItem GetLowestFeeTransaction(SortedSet verifiedTxSorted, + private static PoolItem GetLowestFeeTransaction(SortedSet verifiedTxSorted, SortedSet unverifiedTxSorted, out SortedSet sortedPool) { PoolItem minItem = unverifiedTxSorted.Min; @@ -256,7 +255,7 @@ internal bool CanTransactionFitInPool(Transaction tx) /// /// /// - internal VerifyResult TryAdd(Transaction tx, StoreView snapshot) + internal VerifyResult TryAdd(Transaction tx, DataCache snapshot) { var poolItem = new PoolItem(tx); @@ -349,7 +348,7 @@ internal void InvalidateVerifiedTransactions() } // Note: this must only be called from a single thread (the Blockchain actor) - internal void UpdatePoolForBlockPersisted(Block block, StoreView snapshot) + internal void UpdatePoolForBlockPersisted(Block block, DataCache snapshot) { LoadPolicy(snapshot); @@ -371,11 +370,6 @@ internal void UpdatePoolForBlockPersisted(Block block, StoreView snapshot) _txRwLock.ExitWriteLock(); } - // If we know about headers of future blocks, no point in verifying transactions from the unverified tx pool - // until we get caught up. - if (block.Index > 0 && block.Index < Blockchain.Singleton.HeaderHeight) - return; - ReverifyTransactions(_sortedTransactions, _unverifiedSortedTransactions, _maxTxPerBlock, MaxMillisecondsToReverifyTx, snapshot); } @@ -394,7 +388,7 @@ internal void InvalidateAllTransactions() } private int ReverifyTransactions(SortedSet verifiedSortedTxPool, - SortedSet unverifiedSortedTxPool, int count, double millisecondsTimeout, StoreView snapshot) + SortedSet unverifiedSortedTxPool, int count, double millisecondsTimeout, DataCache snapshot) { DateTime reverifyCutOffTimeStamp = TimeProvider.Current.UtcNow.AddMilliseconds(millisecondsTimeout); List reverifiedItems = new List(count); @@ -470,11 +464,8 @@ private int ReverifyTransactions(SortedSet verifiedSortedTxPool, /// Max transactions to reverify, the value passed can be >=1 /// The snapshot to use for verifying. /// true if more unsorted messages exist, otherwise false - internal bool ReVerifyTopUnverifiedTransactionsIfNeeded(int maxToVerify, StoreView snapshot) + internal bool ReVerifyTopUnverifiedTransactionsIfNeeded(int maxToVerify, DataCache snapshot) { - if (Blockchain.Singleton.Height < Blockchain.Singleton.HeaderHeight) - return false; - if (_unverifiedSortedTransactions.Count > 0) { int verifyCount = _sortedTransactions.Count > _maxTxPerBlock ? 1 : maxToVerify; diff --git a/src/neo/Ledger/TransactionState.cs b/src/neo/Ledger/TransactionState.cs deleted file mode 100644 index c8a479424a..0000000000 --- a/src/neo/Ledger/TransactionState.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Neo.IO; -using Neo.Network.P2P.Payloads; -using Neo.VM; -using System.IO; - -namespace Neo.Ledger -{ - public class TransactionState : ICloneable, ISerializable - { - public uint BlockIndex; - public VMState VMState; - public Transaction Transaction; - - int ISerializable.Size => - sizeof(uint) + // BlockIndex - sizeof(VMState) + // VMState - Transaction.Size; // Transaction - - TransactionState ICloneable.Clone() - { - return new TransactionState - { - BlockIndex = BlockIndex, - VMState = VMState, - Transaction = Transaction - }; - } - - void ISerializable.Deserialize(BinaryReader reader) - { - BlockIndex = reader.ReadUInt32(); - VMState = (VMState)reader.ReadByte(); - Transaction = reader.ReadSerializable(); - } - - void ICloneable.FromReplica(TransactionState replica) - { - BlockIndex = replica.BlockIndex; - VMState = replica.VMState; - Transaction = replica.Transaction; - } - - void ISerializable.Serialize(BinaryWriter writer) - { - writer.Write(BlockIndex); - writer.Write((byte)VMState); - writer.Write(Transaction); - } - } -} diff --git a/src/neo/Ledger/TransactionVerificationContext.cs b/src/neo/Ledger/TransactionVerificationContext.cs index e291974137..cfa9dc15cd 100644 --- a/src/neo/Ledger/TransactionVerificationContext.cs +++ b/src/neo/Ledger/TransactionVerificationContext.cs @@ -29,7 +29,7 @@ public void AddTransaction(Transaction tx) senderFee.Add(tx.Sender, tx.SystemFee + tx.NetworkFee); } - public bool CheckTransaction(Transaction tx, StoreView snapshot) + public bool CheckTransaction(Transaction tx, DataCache snapshot) { BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, tx.Sender); senderFee.TryGetValue(tx.Sender, out var totalSenderFeeFromPool); diff --git a/src/neo/Network/P2P/Payloads/Block.cs b/src/neo/Network/P2P/Payloads/Block.cs index bbea8db9cc..73b1ff97bd 100644 --- a/src/neo/Network/P2P/Payloads/Block.cs +++ b/src/neo/Network/P2P/Payloads/Block.cs @@ -1,19 +1,14 @@ using Neo.Cryptography; using Neo.IO; using Neo.IO.Json; -using Neo.Ledger; -using Neo.SmartContract; -using Neo.VM; -using Neo.VM.Types; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Array = Neo.VM.Types.Array; namespace Neo.Network.P2P.Payloads { - public class Block : BlockBase, IInventory, IEquatable, IInteroperable + public class Block : BlockBase, IInventory, IEquatable { public const int MaxContentsPerBlock = ushort.MaxValue; public const int MaxTransactionsPerBlock = MaxContentsPerBlock - 1; @@ -81,11 +76,6 @@ public override bool Equals(object obj) return Equals(obj as Block); } - void IInteroperable.FromStackItem(StackItem stackItem) - { - throw new NotSupportedException(); - } - public override int GetHashCode() { return Hash.GetHashCode(); @@ -112,41 +102,5 @@ public override JObject ToJson() json["tx"] = Transactions.Select(p => p.ToJson()).ToArray(); return json; } - - public TrimmedBlock Trim() - { - return new TrimmedBlock - { - Version = Version, - PrevHash = PrevHash, - MerkleRoot = MerkleRoot, - Timestamp = Timestamp, - Index = Index, - NextConsensus = NextConsensus, - Witness = Witness, - Hashes = Transactions.Select(p => p.Hash).Prepend(ConsensusData.Hash).ToArray(), - ConsensusData = ConsensusData - }; - } - - public StackItem ToStackItem(ReferenceCounter referenceCounter) - { - return new Array(referenceCounter, new StackItem[] - { - // Computed properties - Hash.ToArray(), - - // BlockBase properties - Version, - PrevHash.ToArray(), - MerkleRoot.ToArray(), - Timestamp, - Index, - NextConsensus.ToArray(), - - // Block properties - Transactions.Length - }); - } } } diff --git a/src/neo/Network/P2P/Payloads/BlockBase.cs b/src/neo/Network/P2P/Payloads/BlockBase.cs index 51dfd3377e..08b2657295 100644 --- a/src/neo/Network/P2P/Payloads/BlockBase.cs +++ b/src/neo/Network/P2P/Payloads/BlockBase.cs @@ -2,6 +2,7 @@ using Neo.IO.Json; using Neo.Persistence; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.Wallets; using System; using System.IO; @@ -72,12 +73,12 @@ void IVerifiable.DeserializeUnsigned(BinaryReader reader) NextConsensus = reader.ReadSerializable(); } - UInt160[] IVerifiable.GetScriptHashesForVerifying(StoreView snapshot) + UInt160[] IVerifiable.GetScriptHashesForVerifying(DataCache snapshot) { if (PrevHash == UInt256.Zero) return new[] { Witness.ScriptHash }; - Header prev_header = snapshot.GetHeader(PrevHash); - if (prev_header == null) throw new InvalidOperationException(); - return new[] { prev_header.NextConsensus }; + TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, PrevHash); + if (prev is null) throw new InvalidOperationException(); + return new[] { prev.NextConsensus }; } public virtual void Serialize(BinaryWriter writer) @@ -111,12 +112,12 @@ public virtual JObject ToJson() return json; } - public virtual bool Verify(StoreView snapshot) + public virtual bool Verify(DataCache snapshot) { - Header prev_header = snapshot.GetHeader(PrevHash); - if (prev_header == null) return false; - if (prev_header.Index + 1 != Index) return false; - if (prev_header.Timestamp >= Timestamp) return false; + TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, PrevHash); + if (prev is null) return false; + if (prev.Index + 1 != Index) return false; + if (prev.Timestamp >= Timestamp) return false; if (!this.VerifyWitnesses(snapshot, 1_00000000)) return false; return true; } diff --git a/src/neo/Network/P2P/Payloads/ExtensiblePayload.cs b/src/neo/Network/P2P/Payloads/ExtensiblePayload.cs index c5414770b2..4e405d4814 100644 --- a/src/neo/Network/P2P/Payloads/ExtensiblePayload.cs +++ b/src/neo/Network/P2P/Payloads/ExtensiblePayload.cs @@ -2,6 +2,7 @@ using Neo.Ledger; using Neo.Persistence; using Neo.SmartContract; +using Neo.SmartContract.Native; using System; using System.IO; @@ -69,7 +70,7 @@ void IVerifiable.DeserializeUnsigned(BinaryReader reader) Data = reader.ReadVarBytes(ushort.MaxValue); } - UInt160[] IVerifiable.GetScriptHashesForVerifying(StoreView snapshot) + UInt160[] IVerifiable.GetScriptHashesForVerifying(DataCache snapshot) { return new[] { Sender }; // This address should be checked by consumer } @@ -89,9 +90,10 @@ void IVerifiable.SerializeUnsigned(BinaryWriter writer) writer.WriteVarBytes(Data); } - public bool Verify(StoreView snapshot) + public bool Verify(DataCache snapshot) { - if (snapshot.Height < ValidBlockStart || snapshot.Height >= ValidBlockEnd) return false; + uint height = NativeContract.Ledger.CurrentIndex(snapshot); + if (height < ValidBlockStart || height >= ValidBlockEnd) return false; if (!Blockchain.Singleton.IsExtensibleWitnessWhiteListed(Sender)) return false; return this.VerifyWitnesses(snapshot, 0_02000000); } diff --git a/src/neo/Network/P2P/Payloads/Header.cs b/src/neo/Network/P2P/Payloads/Header.cs index d227860bb0..301d1cf05b 100644 --- a/src/neo/Network/P2P/Payloads/Header.cs +++ b/src/neo/Network/P2P/Payloads/Header.cs @@ -1,4 +1,3 @@ -using Neo.Ledger; using System; using System.IO; @@ -36,20 +35,5 @@ public override void Serialize(BinaryWriter writer) base.Serialize(writer); writer.Write((byte)0); } - - public TrimmedBlock Trim() - { - return new TrimmedBlock - { - Version = Version, - PrevHash = PrevHash, - MerkleRoot = MerkleRoot, - Timestamp = Timestamp, - Index = Index, - NextConsensus = NextConsensus, - Witness = Witness, - Hashes = new UInt256[0] - }; - } } } diff --git a/src/neo/Network/P2P/Payloads/HighPriorityAttribute.cs b/src/neo/Network/P2P/Payloads/HighPriorityAttribute.cs index 48d4b79a95..d3077d3e88 100644 --- a/src/neo/Network/P2P/Payloads/HighPriorityAttribute.cs +++ b/src/neo/Network/P2P/Payloads/HighPriorityAttribute.cs @@ -18,7 +18,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) { } - public override bool Verify(StoreView snapshot, Transaction tx) + public override bool Verify(DataCache snapshot, Transaction tx) { UInt160 committee = NativeContract.NEO.GetCommitteeAddress(snapshot); return tx.Signers.Any(p => p.Account.Equals(committee)); diff --git a/src/neo/Network/P2P/Payloads/IInventory.cs b/src/neo/Network/P2P/Payloads/IInventory.cs index 2b175647c5..49256132c6 100644 --- a/src/neo/Network/P2P/Payloads/IInventory.cs +++ b/src/neo/Network/P2P/Payloads/IInventory.cs @@ -8,6 +8,6 @@ public interface IInventory : IVerifiable InventoryType InventoryType { get; } - bool Verify(StoreView snapshot); + bool Verify(DataCache snapshot); } } diff --git a/src/neo/Network/P2P/Payloads/IVerifiable.cs b/src/neo/Network/P2P/Payloads/IVerifiable.cs index cecd0570da..3e574366ed 100644 --- a/src/neo/Network/P2P/Payloads/IVerifiable.cs +++ b/src/neo/Network/P2P/Payloads/IVerifiable.cs @@ -10,7 +10,7 @@ public interface IVerifiable : ISerializable void DeserializeUnsigned(BinaryReader reader); - UInt160[] GetScriptHashesForVerifying(StoreView snapshot); + UInt160[] GetScriptHashesForVerifying(DataCache snapshot); void SerializeUnsigned(BinaryWriter writer); } diff --git a/src/neo/Network/P2P/Payloads/OracleResponse.cs b/src/neo/Network/P2P/Payloads/OracleResponse.cs index 77ed8cf7ec..81bf449292 100644 --- a/src/neo/Network/P2P/Payloads/OracleResponse.cs +++ b/src/neo/Network/P2P/Payloads/OracleResponse.cs @@ -1,7 +1,7 @@ using Neo.IO; using Neo.IO.Json; -using Neo.Ledger; using Neo.Persistence; +using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; using System; @@ -62,14 +62,14 @@ public override JObject ToJson() return json; } - public override bool Verify(StoreView snapshot, Transaction tx) + public override bool Verify(DataCache snapshot, Transaction tx) { if (tx.Signers.Any(p => p.Scopes != WitnessScope.None)) return false; if (!tx.Script.AsSpan().SequenceEqual(FixedScript)) return false; OracleRequest request = NativeContract.Oracle.GetRequest(snapshot, Id); if (request is null) return false; if (tx.NetworkFee + tx.SystemFee != request.GasForResponse) return false; - UInt160 oracleAccount = Blockchain.GetConsensusAddress(NativeContract.RoleManagement.GetDesignatedByRole(snapshot, Role.Oracle, snapshot.Height + 1)); + UInt160 oracleAccount = Contract.GetBFTAddress(NativeContract.RoleManagement.GetDesignatedByRole(snapshot, Role.Oracle, NativeContract.Ledger.CurrentIndex(snapshot) + 1)); return tx.Signers.Any(p => p.Account.Equals(oracleAccount)); } } diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 77252f04c6..2007c8c202 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -235,7 +235,7 @@ public override int GetHashCode() return Hash.GetHashCode(); } - public UInt160[] GetScriptHashesForVerifying(StoreView snapshot) + public UInt160[] GetScriptHashesForVerifying(DataCache snapshot) { return Signers.Select(p => p.Account).ToArray(); } @@ -276,14 +276,15 @@ public JObject ToJson() return json; } - bool IInventory.Verify(StoreView snapshot) + bool IInventory.Verify(DataCache snapshot) { return Verify(snapshot, null) == VerifyResult.Succeed; } - public virtual VerifyResult VerifyStateDependent(StoreView snapshot, TransactionVerificationContext context) + public virtual VerifyResult VerifyStateDependent(DataCache snapshot, TransactionVerificationContext context) { - if (ValidUntilBlock <= snapshot.Height || ValidUntilBlock > snapshot.Height + MaxValidUntilBlockIncrement) + uint height = NativeContract.Ledger.CurrentIndex(snapshot); + if (ValidUntilBlock <= height || ValidUntilBlock > height + MaxValidUntilBlockIncrement) return VerifyResult.Expired; foreach (UInt160 hash in GetScriptHashesForVerifying(snapshot)) if (NativeContract.Policy.IsBlocked(snapshot, hash)) @@ -330,7 +331,7 @@ public virtual VerifyResult VerifyStateIndependent() return VerifyResult.Succeed; } - public virtual VerifyResult Verify(StoreView snapshot, TransactionVerificationContext context) + public virtual VerifyResult Verify(DataCache snapshot, TransactionVerificationContext context) { VerifyResult result = VerifyStateIndependent(); if (result != VerifyResult.Succeed) return result; diff --git a/src/neo/Network/P2P/Payloads/TransactionAttribute.cs b/src/neo/Network/P2P/Payloads/TransactionAttribute.cs index 98583aa5d6..acd3238119 100644 --- a/src/neo/Network/P2P/Payloads/TransactionAttribute.cs +++ b/src/neo/Network/P2P/Payloads/TransactionAttribute.cs @@ -47,6 +47,6 @@ public void Serialize(BinaryWriter writer) protected abstract void SerializeWithoutType(BinaryWriter writer); - public virtual bool Verify(StoreView snapshot, Transaction tx) => true; + public virtual bool Verify(DataCache snapshot, Transaction tx) => true; } } diff --git a/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs b/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs index 7d85875c56..0cb6b1afcb 100644 --- a/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs +++ b/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs @@ -6,6 +6,7 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.Plugins; +using Neo.SmartContract.Native; using System; using System.Collections; using System.Collections.Generic; @@ -169,20 +170,23 @@ private void OnGetAddrMessageReceived() /// A GetBlocksPayload including start block Hash and number of blocks requested. private void OnGetBlocksMessageReceived(GetBlocksPayload payload) { - UInt256 hash = payload.HashStart; - // The default value of payload.Count is -1 - int count = payload.Count < 0 || payload.Count > InvPayload.MaxHashesCount ? InvPayload.MaxHashesCount : payload.Count; - TrimmedBlock state = Blockchain.Singleton.View.Blocks.TryGet(hash); - if (state == null) return; List hashes = new List(); - for (uint i = 1; i <= count; i++) + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) { - uint index = state.Index + i; - if (index > Blockchain.Singleton.Height) - break; - hash = Blockchain.Singleton.GetBlockHash(index); - if (hash == null) break; - hashes.Add(hash); + UInt256 hash = payload.HashStart; + // The default value of payload.Count is -1 + int count = payload.Count < 0 || payload.Count > InvPayload.MaxHashesCount ? InvPayload.MaxHashesCount : payload.Count; + TrimmedBlock state = NativeContract.Ledger.GetTrimmedBlock(snapshot, hash); + if (state == null) return; + for (uint i = 1; i <= count; i++) + { + uint index = state.Index + i; + if (index > Blockchain.Singleton.Height) + break; + hash = NativeContract.Ledger.GetBlockHash(snapshot, index); + if (hash == null) break; + hashes.Add(hash); + } } if (hashes.Count == 0) return; EnqueueMessage(Message.Create(MessageCommand.Inv, InvPayload.Create(InventoryType.Block, hashes.ToArray()))); @@ -193,7 +197,7 @@ private void OnGetBlockByIndexMessageReceived(GetBlockByIndexPayload payload) uint count = payload.Count == -1 ? InvPayload.MaxHashesCount : Math.Min((uint)payload.Count, InvPayload.MaxHashesCount); for (uint i = payload.IndexStart, max = payload.IndexStart + count; i < max; i++) { - Block block = Blockchain.Singleton.GetBlock(i); + Block block = NativeContract.Ledger.GetBlock(Blockchain.Singleton.View, i); if (block == null) break; @@ -223,14 +227,13 @@ private void OnGetDataMessageReceived(InvPayload payload) switch (payload.Type) { case InventoryType.TX: - Transaction tx = Blockchain.Singleton.GetTransaction(hash); - if (tx != null) + if (Blockchain.Singleton.MemPool.TryGetValue(hash, out Transaction tx)) EnqueueMessage(Message.Create(MessageCommand.Transaction, tx)); else notFound.Add(hash); break; case InventoryType.Block: - Block block = Blockchain.Singleton.GetBlock(hash); + Block block = NativeContract.Ledger.GetBlock(Blockchain.Singleton.View, hash); if (block != null) { if (bloom_filter == null) @@ -271,15 +274,17 @@ private void OnGetDataMessageReceived(InvPayload payload) private void OnGetHeadersMessageReceived(GetBlockByIndexPayload payload) { uint index = payload.IndexStart; - uint count = payload.Count == -1 ? HeadersPayload.MaxHeadersCount : (uint)payload.Count; - if (index > Blockchain.Singleton.HeaderHeight) - return; + if (index > Blockchain.Singleton.Height) return; List
headers = new List
(); - for (uint i = 0; i < count; i++) + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) { - var header = Blockchain.Singleton.GetHeader(index + i); - if (header == null) break; - headers.Add(header); + uint count = payload.Count == -1 ? HeadersPayload.MaxHeadersCount : (uint)payload.Count; + for (uint i = 0; i < count; i++) + { + var header = NativeContract.Ledger.GetHeader(snapshot, index + i); + if (header == null) break; + headers.Add(header); + } } if (headers.Count == 0) return; EnqueueMessage(Message.Create(MessageCommand.Headers, HeadersPayload.Create(headers.ToArray()))); @@ -305,12 +310,12 @@ private void OnInvMessageReceived(InvPayload payload) switch (payload.Type) { case InventoryType.Block: - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) - hashes = hashes.Where(p => !snapshot.ContainsBlock(p)).ToArray(); + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) + hashes = hashes.Where(p => !NativeContract.Ledger.ContainsBlock(snapshot, p)).ToArray(); break; case InventoryType.TX: - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) - hashes = hashes.Where(p => !snapshot.ContainsTransaction(p)).ToArray(); + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) + hashes = hashes.Where(p => !NativeContract.Ledger.ContainsTransaction(snapshot, p)).ToArray(); break; } if (hashes.Length == 0) return; diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index ef6e09e443..1e11baf4e0 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -5,6 +5,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.SmartContract.Native; using System; using System.Collections; using System.Collections.Generic; @@ -302,9 +303,9 @@ private void RequestTasks(bool sendPing) private void SendPingMessage() { TrimmedBlock block; - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) { - block = snapshot.Blocks[snapshot.CurrentBlockHash]; + block = NativeContract.Ledger.GetTrimmedBlock(snapshot, NativeContract.Ledger.CurrentHash(snapshot)); } foreach (KeyValuePair item in sessions) diff --git a/src/neo/Persistence/ClonedCache.cs b/src/neo/Persistence/ClonedCache.cs new file mode 100644 index 0000000000..3fc52bc2ab --- /dev/null +++ b/src/neo/Persistence/ClonedCache.cs @@ -0,0 +1,51 @@ +using Neo.SmartContract; +using System.Collections.Generic; + +namespace Neo.Persistence +{ + class ClonedCache : DataCache + { + private readonly DataCache innerCache; + + public ClonedCache(DataCache innerCache) + { + this.innerCache = innerCache; + } + + protected override void AddInternal(StorageKey key, StorageItem value) + { + innerCache.Add(key, value); + } + + protected override void DeleteInternal(StorageKey key) + { + innerCache.Delete(key); + } + + protected override bool ContainsInternal(StorageKey key) + { + return innerCache.Contains(key); + } + + protected override StorageItem GetInternal(StorageKey key) + { + return innerCache[key].Clone(); + } + + protected override IEnumerable<(StorageKey, StorageItem)> SeekInternal(byte[] keyOrPreifx, SeekDirection direction) + { + foreach (var (key, value) in innerCache.Seek(keyOrPreifx, direction)) + yield return (key, value.Clone()); + } + + protected override StorageItem TryGetInternal(StorageKey key) + { + return innerCache.TryGet(key)?.Clone(); + } + + protected override void UpdateInternal(StorageKey key, StorageItem value) + { + innerCache.GetAndChange(key).FromReplica(value); + } + } +} diff --git a/src/neo/Persistence/ClonedView.cs b/src/neo/Persistence/ClonedView.cs deleted file mode 100644 index 3b9b8017e6..0000000000 --- a/src/neo/Persistence/ClonedView.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Neo.IO; -using Neo.IO.Caching; -using Neo.Ledger; - -namespace Neo.Persistence -{ - internal class ClonedView : StoreView - { - public override DataCache Blocks { get; } - public override DataCache Transactions { get; } - public override DataCache Storages { get; } - public override DataCache, HeaderHashList> HeaderHashList { get; } - public override MetaDataCache BlockHashIndex { get; } - public override MetaDataCache HeaderHashIndex { get; } - - public ClonedView(StoreView view) - { - this.Blocks = view.Blocks.CreateSnapshot(); - this.Transactions = view.Transactions.CreateSnapshot(); - this.Storages = view.Storages.CreateSnapshot(); - this.HeaderHashList = view.HeaderHashList.CreateSnapshot(); - this.BlockHashIndex = view.BlockHashIndex.CreateSnapshot(); - this.HeaderHashIndex = view.HeaderHashIndex.CreateSnapshot(); - } - } -} diff --git a/src/neo/IO/Caching/DataCache.cs b/src/neo/Persistence/DataCache.cs similarity index 82% rename from src/neo/IO/Caching/DataCache.cs rename to src/neo/Persistence/DataCache.cs index b81ad3d7f7..a5b96fc5fe 100644 --- a/src/neo/IO/Caching/DataCache.cs +++ b/src/neo/Persistence/DataCache.cs @@ -1,24 +1,24 @@ +using Neo.IO; +using Neo.SmartContract; using System; using System.Collections.Generic; using System.Linq; -namespace Neo.IO.Caching +namespace Neo.Persistence { - public abstract class DataCache - where TKey : IEquatable, ISerializable - where TValue : class, ICloneable, ISerializable, new() + public abstract class DataCache { public class Trackable { - public TKey Key; - public TValue Item; + public StorageKey Key; + public StorageItem Item; public TrackState State; } - private readonly Dictionary dictionary = new Dictionary(); - private readonly HashSet changeSet = new HashSet(); + private readonly Dictionary dictionary = new Dictionary(); + private readonly HashSet changeSet = new HashSet(); - public TValue this[TKey key] + public StorageItem this[StorageKey key] { get { @@ -54,7 +54,7 @@ public TValue this[TKey key] /// /// Corresponding value to be added, in the case of sucess. /// If cached on dictionary, with any state rather than `Deleted`, an Exception will be raised. - public void Add(TKey key, TValue value) + public void Add(StorageKey key, StorageItem value) { lock (dictionary) { @@ -70,14 +70,14 @@ public void Add(TKey key, TValue value) } } - protected abstract void AddInternal(TKey key, TValue value); + protected abstract void AddInternal(StorageKey key, StorageItem value); /// /// Update internals with all changes cached on Dictionary which are not None. /// - public void Commit() + public virtual void Commit() { - LinkedList deletedItem = new LinkedList(); + LinkedList deletedItem = new LinkedList(); foreach (Trackable trackable in GetChangeSet()) switch (trackable.State) { @@ -94,23 +94,23 @@ public void Commit() deletedItem.AddFirst(trackable.Key); break; } - foreach (TKey key in deletedItem) + foreach (StorageKey key in deletedItem) { dictionary.Remove(key); } changeSet.Clear(); } - public DataCache CreateSnapshot() + public DataCache CreateSnapshot() { - return new CloneCache(this); + return new ClonedCache(this); } /// /// Delete key from cached Dictionary or search in Internal. /// /// Key to be deleted. - public void Delete(TKey key) + public void Delete(StorageKey key) { lock (dictionary) { @@ -129,7 +129,7 @@ public void Delete(TKey key) } else { - TValue item = TryGetInternal(key); + StorageItem item = TryGetInternal(key); if (item == null) return; dictionary.Add(key, new Trackable { @@ -142,14 +142,14 @@ public void Delete(TKey key) } } - protected abstract void DeleteInternal(TKey key); + protected abstract void DeleteInternal(StorageKey key); /// /// Find the entries that start with the `key_prefix` /// - /// Must maintain the deserialized format of TKey + /// Must maintain the deserialized format of StorageKey /// Entries found with the desired prefix - public IEnumerable<(TKey Key, TValue Value)> Find(byte[] key_prefix = null) + public IEnumerable<(StorageKey Key, StorageItem Value)> Find(byte[] key_prefix = null) { foreach (var (key, value) in Seek(key_prefix, SeekDirection.Forward)) if (key.ToArray().AsSpan().StartsWith(key_prefix)) @@ -165,7 +165,7 @@ public void Delete(TKey key) /// End key (exclusive) /// The search direction. /// Entries found with the desired range - public IEnumerable<(TKey Key, TValue Value)> FindRange(byte[] start, byte[] end, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(StorageKey Key, StorageItem Value)> FindRange(byte[] start, byte[] end, SeekDirection direction = SeekDirection.Forward) { ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default @@ -181,12 +181,12 @@ public IEnumerable GetChangeSet() { lock (dictionary) { - foreach (TKey key in changeSet) + foreach (StorageKey key in changeSet) yield return dictionary[key]; } } - public bool Contains(TKey key) + public bool Contains(StorageKey key) { lock (dictionary) { @@ -199,9 +199,9 @@ public bool Contains(TKey key) } } - protected abstract bool ContainsInternal(TKey key); + protected abstract bool ContainsInternal(StorageKey key); - protected abstract TValue GetInternal(TKey key); + protected abstract StorageItem GetInternal(StorageKey key); /// /// Try to Get a specific key from current cached dictionary. @@ -211,7 +211,7 @@ public bool Contains(TKey key) /// Function that may replace current object stored. /// If object already exists the factory passed as parameter will not be used. /// - public TValue GetAndChange(TKey key, Func factory = null) + public StorageItem GetAndChange(StorageKey key, Func factory = null) { lock (dictionary) { @@ -253,7 +253,7 @@ public TValue GetAndChange(TKey key, Func factory = null) } } - public TValue GetOrAdd(TKey key, Func factory) + public StorageItem GetOrAdd(StorageKey key, Func factory) { lock (dictionary) { @@ -294,10 +294,10 @@ public TValue GetOrAdd(TKey key, Func factory) /// The key to be sought /// The direction of seek /// An enumerator containing all the entries after seeking. - public IEnumerable<(TKey Key, TValue Value)> Seek(byte[] keyOrPrefix = null, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(StorageKey Key, StorageItem Value)> Seek(byte[] keyOrPrefix = null, SeekDirection direction = SeekDirection.Forward) { - IEnumerable<(byte[], TKey, TValue)> cached; - HashSet cachedKeySet; + IEnumerable<(byte[], StorageKey, StorageItem)> cached; + HashSet cachedKeySet; ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse; lock (dictionary) { @@ -311,7 +311,7 @@ public TValue GetOrAdd(TKey key, Func factory) )) .OrderBy(p => p.KeyBytes, comparer) .ToArray(); - cachedKeySet = new HashSet(dictionary.Keys); + cachedKeySet = new HashSet(dictionary.Keys); } var uncached = SeekInternal(keyOrPrefix ?? Array.Empty(), direction) .Where(p => !cachedKeySet.Contains(p.Key)) @@ -324,7 +324,7 @@ public TValue GetOrAdd(TKey key, Func factory) using (var e1 = cached.GetEnumerator()) using (var e2 = uncached.GetEnumerator()) { - (byte[] KeyBytes, TKey Key, TValue Item) i1, i2; + (byte[] KeyBytes, StorageKey Key, StorageItem Item) i1, i2; bool c1 = e1.MoveNext(); bool c2 = e2.MoveNext(); i1 = c1 ? e1.Current : default; @@ -347,9 +347,9 @@ public TValue GetOrAdd(TKey key, Func factory) } } - protected abstract IEnumerable<(TKey Key, TValue Value)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction); + protected abstract IEnumerable<(StorageKey Key, StorageItem Value)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction); - public TValue TryGet(TKey key) + public StorageItem TryGet(StorageKey key) { lock (dictionary) { @@ -358,7 +358,7 @@ public TValue TryGet(TKey key) if (trackable.State == TrackState.Deleted) return null; return trackable.Item; } - TValue value = TryGetInternal(key); + StorageItem value = TryGetInternal(key); if (value == null) return null; dictionary.Add(key, new Trackable { @@ -370,8 +370,8 @@ public TValue TryGet(TKey key) } } - protected abstract TValue TryGetInternal(TKey key); + protected abstract StorageItem TryGetInternal(StorageKey key); - protected abstract void UpdateInternal(TKey key, TValue value); + protected abstract void UpdateInternal(StorageKey key, StorageItem value); } } diff --git a/src/neo/Persistence/IReadOnlyStore.cs b/src/neo/Persistence/IReadOnlyStore.cs index 86b7ef4877..f13fd56d7f 100644 --- a/src/neo/Persistence/IReadOnlyStore.cs +++ b/src/neo/Persistence/IReadOnlyStore.cs @@ -8,8 +8,8 @@ namespace Neo.Persistence /// public interface IReadOnlyStore { - IEnumerable<(byte[] Key, byte[] Value)> Seek(byte table, byte[] key, SeekDirection direction); - byte[] TryGet(byte table, byte[] key); - bool Contains(byte table, byte[] key); + IEnumerable<(byte[] Key, byte[] Value)> Seek(byte[] key, SeekDirection direction); + byte[] TryGet(byte[] key); + bool Contains(byte[] key); } } diff --git a/src/neo/Persistence/ISnapshot.cs b/src/neo/Persistence/ISnapshot.cs index 335089d4bc..12bb0780af 100644 --- a/src/neo/Persistence/ISnapshot.cs +++ b/src/neo/Persistence/ISnapshot.cs @@ -8,7 +8,7 @@ namespace Neo.Persistence public interface ISnapshot : IDisposable, IReadOnlyStore { void Commit(); - void Delete(byte table, byte[] key); - void Put(byte table, byte[] key, byte[] value); + void Delete(byte[] key); + void Put(byte[] key, byte[] value); } } diff --git a/src/neo/Persistence/IStore.cs b/src/neo/Persistence/IStore.cs index 197cecdca3..dbf2087760 100644 --- a/src/neo/Persistence/IStore.cs +++ b/src/neo/Persistence/IStore.cs @@ -7,12 +7,9 @@ namespace Neo.Persistence /// public interface IStore : IDisposable, IReadOnlyStore { - void Delete(byte table, byte[] key); + void Delete(byte[] key); ISnapshot GetSnapshot(); - void Put(byte table, byte[] key, byte[] value); - void PutSync(byte table, byte[] key, byte[] value) - { - Put(table, key, value); - } + void Put(byte[] key, byte[] value); + void PutSync(byte[] key, byte[] value) => Put(key, value); } } diff --git a/src/neo/Persistence/MemorySnapshot.cs b/src/neo/Persistence/MemorySnapshot.cs index e5800c08ae..7b3c77dbe8 100644 --- a/src/neo/Persistence/MemorySnapshot.cs +++ b/src/neo/Persistence/MemorySnapshot.cs @@ -9,62 +9,59 @@ namespace Neo.Persistence { internal class MemorySnapshot : ISnapshot { - private readonly ConcurrentDictionary[] innerData; - private readonly ImmutableDictionary[] immutableData; - private readonly ConcurrentDictionary[] writeBatch; + private readonly ConcurrentDictionary innerData; + private readonly ImmutableDictionary immutableData; + private readonly ConcurrentDictionary writeBatch; - public MemorySnapshot(ConcurrentDictionary[] innerData) + public MemorySnapshot(ConcurrentDictionary innerData) { this.innerData = innerData; - this.immutableData = innerData.Select(p => p.ToImmutableDictionary(ByteArrayEqualityComparer.Default)).ToArray(); - this.writeBatch = new ConcurrentDictionary[innerData.Length]; - for (int i = 0; i < writeBatch.Length; i++) - writeBatch[i] = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); + this.immutableData = innerData.ToImmutableDictionary(ByteArrayEqualityComparer.Default); + this.writeBatch = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); } public void Commit() { - for (int i = 0; i < writeBatch.Length; i++) - foreach (var pair in writeBatch[i]) - if (pair.Value is null) - innerData[i].TryRemove(pair.Key, out _); - else - innerData[i][pair.Key] = pair.Value; + foreach (var pair in writeBatch) + if (pair.Value is null) + innerData.TryRemove(pair.Key, out _); + else + innerData[pair.Key] = pair.Value; } - public void Delete(byte table, byte[] key) + public void Delete(byte[] key) { - writeBatch[table][key.EnsureNotNull()] = null; + writeBatch[key.EnsureNotNull()] = null; } public void Dispose() { } - public void Put(byte table, byte[] key, byte[] value) + public void Put(byte[] key, byte[] value) { - writeBatch[table][key.EnsureNotNull()] = value; + writeBatch[key.EnsureNotNull()] = value; } - public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte table, byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) { ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse; - IEnumerable> records = immutableData[table]; + IEnumerable> records = immutableData; if (keyOrPrefix?.Length > 0) records = records.Where(p => comparer.Compare(p.Key, keyOrPrefix) >= 0); records = records.OrderBy(p => p.Key, comparer); return records.Select(p => (p.Key, p.Value)); } - public byte[] TryGet(byte table, byte[] key) + public byte[] TryGet(byte[] key) { - immutableData[table].TryGetValue(key.EnsureNotNull(), out byte[] value); + immutableData.TryGetValue(key.EnsureNotNull(), out byte[] value); return value; } - public bool Contains(byte table, byte[] key) + public bool Contains(byte[] key) { - return innerData[table].ContainsKey(key.EnsureNotNull()); + return innerData.ContainsKey(key.EnsureNotNull()); } } } diff --git a/src/neo/Persistence/MemoryStore.cs b/src/neo/Persistence/MemoryStore.cs index fdcd06f013..705f509b87 100644 --- a/src/neo/Persistence/MemoryStore.cs +++ b/src/neo/Persistence/MemoryStore.cs @@ -8,18 +8,11 @@ namespace Neo.Persistence { public class MemoryStore : IStore { - private readonly ConcurrentDictionary[] innerData; + private readonly ConcurrentDictionary innerData = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); - public MemoryStore() + public void Delete(byte[] key) { - innerData = new ConcurrentDictionary[256]; - for (int i = 0; i < innerData.Length; i++) - innerData[i] = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); - } - - public void Delete(byte table, byte[] key) - { - innerData[table].TryRemove(key.EnsureNotNull(), out _); + innerData.TryRemove(key.EnsureNotNull(), out _); } public void Dispose() @@ -31,15 +24,15 @@ public ISnapshot GetSnapshot() return new MemorySnapshot(innerData); } - public void Put(byte table, byte[] key, byte[] value) + public void Put(byte[] key, byte[] value) { - innerData[table][key.EnsureNotNull()] = value; + innerData[key.EnsureNotNull()] = value; } - public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte table, byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) { ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse; - IEnumerable> records = innerData[table]; + IEnumerable> records = innerData; if (keyOrPrefix?.Length > 0) records = records.Where(p => comparer.Compare(p.Key, keyOrPrefix) >= 0); records = records.OrderBy(p => p.Key, comparer); @@ -47,15 +40,15 @@ public void Put(byte table, byte[] key, byte[] value) yield return (pair.Key, pair.Value); } - public byte[] TryGet(byte table, byte[] key) + public byte[] TryGet(byte[] key) { - innerData[table].TryGetValue(key.EnsureNotNull(), out byte[] value); + innerData.TryGetValue(key.EnsureNotNull(), out byte[] value); return value; } - public bool Contains(byte table, byte[] key) + public bool Contains(byte[] key) { - return innerData[table].ContainsKey(key.EnsureNotNull()); + return innerData.ContainsKey(key.EnsureNotNull()); } } } diff --git a/src/neo/Persistence/Prefixes.cs b/src/neo/Persistence/Prefixes.cs deleted file mode 100644 index 3b63665326..0000000000 --- a/src/neo/Persistence/Prefixes.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Neo.Persistence -{ - internal static class Prefixes - { - public const byte DATA_Block = 0x01; - public const byte DATA_Transaction = 0x02; - - public const byte ST_Storage = 0x70; - - public const byte IX_HeaderHashList = 0x80; - public const byte IX_CurrentBlock = 0xc0; - public const byte IX_CurrentHeader = 0xc1; - } -} diff --git a/src/neo/Persistence/ReadOnlyView.cs b/src/neo/Persistence/ReadOnlyView.cs deleted file mode 100644 index a874c33697..0000000000 --- a/src/neo/Persistence/ReadOnlyView.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Neo.IO; -using Neo.IO.Caching; -using Neo.Ledger; -using System; - -namespace Neo.Persistence -{ - /// - /// Provide a read-only for accessing directly from database instead of from snapshot. - /// - public class ReadOnlyView : StoreView - { - private readonly IReadOnlyStore store; - - public override DataCache Blocks => new StoreDataCache(store, Prefixes.DATA_Block); - public override DataCache Transactions => new StoreDataCache(store, Prefixes.DATA_Transaction); - public override DataCache Storages => new StoreDataCache(store, Prefixes.ST_Storage); - public override DataCache, HeaderHashList> HeaderHashList => new StoreDataCache, HeaderHashList>(store, Prefixes.IX_HeaderHashList); - public override MetaDataCache BlockHashIndex => new StoreMetaDataCache(store, Prefixes.IX_CurrentBlock); - public override MetaDataCache HeaderHashIndex => new StoreMetaDataCache(store, Prefixes.IX_CurrentHeader); - - public ReadOnlyView(IReadOnlyStore store) - { - this.store = store; - } - - public override void Commit() - { - throw new NotSupportedException(); - } - } -} diff --git a/src/neo/IO/Caching/SeekDirection.cs b/src/neo/Persistence/SeekDirection.cs similarity index 78% rename from src/neo/IO/Caching/SeekDirection.cs rename to src/neo/Persistence/SeekDirection.cs index 5387fd8311..ca48561ab3 100644 --- a/src/neo/IO/Caching/SeekDirection.cs +++ b/src/neo/Persistence/SeekDirection.cs @@ -1,4 +1,4 @@ -namespace Neo.IO.Caching +namespace Neo.Persistence { public enum SeekDirection : sbyte { diff --git a/src/neo/Persistence/SnapshotCache.cs b/src/neo/Persistence/SnapshotCache.cs new file mode 100644 index 0000000000..a6e6bf9452 --- /dev/null +++ b/src/neo/Persistence/SnapshotCache.cs @@ -0,0 +1,66 @@ +using Neo.IO; +using Neo.SmartContract; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Neo.Persistence +{ + public class SnapshotCache : DataCache, IDisposable + { + private readonly IReadOnlyStore store; + private readonly ISnapshot snapshot; + + public SnapshotCache(IReadOnlyStore store) + { + this.store = store; + this.snapshot = store as ISnapshot; + } + + protected override void AddInternal(StorageKey key, StorageItem value) + { + snapshot?.Put(key.ToArray(), value.ToArray()); + } + + protected override void DeleteInternal(StorageKey key) + { + snapshot?.Delete(key.ToArray()); + } + + public override void Commit() + { + base.Commit(); + snapshot.Commit(); + } + + protected override bool ContainsInternal(StorageKey key) + { + return store.Contains(key.ToArray()); + } + + public void Dispose() + { + snapshot?.Dispose(); + } + + protected override StorageItem GetInternal(StorageKey key) + { + return store.TryGet(key.ToArray()).AsSerializable(); + } + + protected override IEnumerable<(StorageKey, StorageItem)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction) + { + return store.Seek(keyOrPrefix, direction).Select(p => (p.Key.AsSerializable(), p.Value.AsSerializable())); + } + + protected override StorageItem TryGetInternal(StorageKey key) + { + return store.TryGet(key.ToArray())?.AsSerializable(); + } + + protected override void UpdateInternal(StorageKey key, StorageItem value) + { + snapshot?.Put(key.ToArray(), value.ToArray()); + } + } +} diff --git a/src/neo/Persistence/SnapshotView.cs b/src/neo/Persistence/SnapshotView.cs deleted file mode 100644 index ce66270509..0000000000 --- a/src/neo/Persistence/SnapshotView.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Neo.IO; -using Neo.IO.Caching; -using Neo.Ledger; -using System; - -namespace Neo.Persistence -{ - /// - /// Provide a for accessing snapshots. - /// - public class SnapshotView : StoreView, IDisposable - { - private readonly ISnapshot snapshot; - - public override DataCache Blocks { get; } - public override DataCache Transactions { get; } - public override DataCache Storages { get; } - public override DataCache, HeaderHashList> HeaderHashList { get; } - public override MetaDataCache BlockHashIndex { get; } - public override MetaDataCache HeaderHashIndex { get; } - - public SnapshotView(IStore store) - { - this.snapshot = store.GetSnapshot(); - Blocks = new StoreDataCache(snapshot, Prefixes.DATA_Block); - Transactions = new StoreDataCache(snapshot, Prefixes.DATA_Transaction); - Storages = new StoreDataCache(snapshot, Prefixes.ST_Storage); - HeaderHashList = new StoreDataCache, HeaderHashList>(snapshot, Prefixes.IX_HeaderHashList); - BlockHashIndex = new StoreMetaDataCache(snapshot, Prefixes.IX_CurrentBlock); - HeaderHashIndex = new StoreMetaDataCache(snapshot, Prefixes.IX_CurrentHeader); - } - - public override void Commit() - { - base.Commit(); - snapshot.Commit(); - } - - public void Dispose() - { - snapshot.Dispose(); - } - } -} diff --git a/src/neo/Persistence/StoreDataCache.cs b/src/neo/Persistence/StoreDataCache.cs deleted file mode 100644 index 570114198d..0000000000 --- a/src/neo/Persistence/StoreDataCache.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Neo.IO; -using Neo.IO.Caching; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Neo.Persistence -{ - public class StoreDataCache : DataCache - where TKey : IEquatable, ISerializable, new() - where TValue : class, ICloneable, ISerializable, new() - { - private readonly IReadOnlyStore store; - private readonly ISnapshot snapshot; - private readonly byte prefix; - - public StoreDataCache(IReadOnlyStore store, byte prefix) - { - this.store = store; - this.snapshot = store as ISnapshot; - this.prefix = prefix; - } - - protected override void AddInternal(TKey key, TValue value) - { - snapshot?.Put(prefix, key.ToArray(), value.ToArray()); - } - - protected override void DeleteInternal(TKey key) - { - snapshot?.Delete(prefix, key.ToArray()); - } - - protected override bool ContainsInternal(TKey key) - { - return store.Contains(prefix, key.ToArray()); - } - - protected override TValue GetInternal(TKey key) - { - return store.TryGet(prefix, key.ToArray()).AsSerializable(); - } - - protected override IEnumerable<(TKey, TValue)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction) - { - return store.Seek(prefix, keyOrPrefix, direction).Select(p => (p.Key.AsSerializable(), p.Value.AsSerializable())); - } - - protected override TValue TryGetInternal(TKey key) - { - return store.TryGet(prefix, key.ToArray())?.AsSerializable(); - } - - protected override void UpdateInternal(TKey key, TValue value) - { - snapshot?.Put(prefix, key.ToArray(), value.ToArray()); - } - } -} diff --git a/src/neo/Persistence/StoreMetaDataCache.cs b/src/neo/Persistence/StoreMetaDataCache.cs deleted file mode 100644 index 043eb20a07..0000000000 --- a/src/neo/Persistence/StoreMetaDataCache.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Neo.IO; -using Neo.IO.Caching; -using System; - -namespace Neo.Persistence -{ - public class StoreMetaDataCache : MetaDataCache - where T : class, ICloneable, ISerializable, new() - { - private readonly IReadOnlyStore store; - private readonly ISnapshot snapshot; - private readonly byte prefix; - - public StoreMetaDataCache(IReadOnlyStore store, byte prefix, Func factory = null) - : base(factory) - { - this.store = store; - this.snapshot = store as ISnapshot; - this.prefix = prefix; - } - - protected override void AddInternal(T item) - { - snapshot?.Put(prefix, null, item.ToArray()); - } - - protected override T TryGetInternal() - { - return store.TryGet(prefix, null)?.AsSerializable(); - } - - protected override void UpdateInternal(T item) - { - snapshot?.Put(prefix, null, item.ToArray()); - } - } -} diff --git a/src/neo/Persistence/StoreView.cs b/src/neo/Persistence/StoreView.cs deleted file mode 100644 index a31d27ec57..0000000000 --- a/src/neo/Persistence/StoreView.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Neo.IO; -using Neo.IO.Caching; -using Neo.Ledger; -using Neo.Network.P2P.Payloads; - -namespace Neo.Persistence -{ - /// - /// It provides a set of properties and methods for reading formatted data from the underlying storage. Such as and . - /// - public abstract class StoreView - { - public abstract DataCache Blocks { get; } - public abstract DataCache Transactions { get; } - public abstract DataCache Storages { get; } - public abstract DataCache, HeaderHashList> HeaderHashList { get; } - public abstract MetaDataCache BlockHashIndex { get; } - public abstract MetaDataCache HeaderHashIndex { get; } - - public uint Height => BlockHashIndex.Get().Index; - public uint HeaderHeight => HeaderHashIndex.Get().Index; - public UInt256 CurrentBlockHash => BlockHashIndex.Get().Hash; - public UInt256 CurrentHeaderHash => HeaderHashIndex.Get().Hash; - - public StoreView Clone() - { - return new ClonedView(this); - } - - public virtual void Commit() - { - Blocks.Commit(); - Transactions.Commit(); - Storages.Commit(); - HeaderHashList.Commit(); - BlockHashIndex.Commit(); - HeaderHashIndex.Commit(); - } - - public bool ContainsBlock(UInt256 hash) - { - TrimmedBlock state = Blocks.TryGet(hash); - if (state == null) return false; - return state.IsBlock; - } - - public bool ContainsTransaction(UInt256 hash) - { - return Transactions.Contains(hash); - } - - public Block GetBlock(UInt256 hash) - { - TrimmedBlock state = Blocks.TryGet(hash); - if (state == null) return null; - if (!state.IsBlock) return null; - return state.GetBlock(Transactions); - } - - public Header GetHeader(UInt256 hash) - { - return Blocks.TryGet(hash)?.Header; - } - - public Transaction GetTransaction(UInt256 hash) - { - return Transactions.TryGet(hash)?.Transaction; - } - } -} diff --git a/src/neo/IO/Caching/TrackState.cs b/src/neo/Persistence/TrackState.cs similarity index 81% rename from src/neo/IO/Caching/TrackState.cs rename to src/neo/Persistence/TrackState.cs index cba7daec0c..30bc210539 100644 --- a/src/neo/IO/Caching/TrackState.cs +++ b/src/neo/Persistence/TrackState.cs @@ -1,4 +1,4 @@ -namespace Neo.IO.Caching +namespace Neo.Persistence { public enum TrackState : byte { diff --git a/src/neo/Plugins/IApplicationEngineProvider.cs b/src/neo/Plugins/IApplicationEngineProvider.cs index df3427219c..43f50daa3a 100644 --- a/src/neo/Plugins/IApplicationEngineProvider.cs +++ b/src/neo/Plugins/IApplicationEngineProvider.cs @@ -6,6 +6,6 @@ namespace Neo.Plugins { public interface IApplicationEngineProvider { - ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, Block persistingBlock, long gas); + ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, long gas); } } diff --git a/src/neo/Plugins/IPersistencePlugin.cs b/src/neo/Plugins/IPersistencePlugin.cs index 64be4b8b0b..76bb126cc5 100644 --- a/src/neo/Plugins/IPersistencePlugin.cs +++ b/src/neo/Plugins/IPersistencePlugin.cs @@ -8,8 +8,8 @@ namespace Neo.Plugins { public interface IPersistencePlugin { - void OnPersist(Block block, StoreView snapshot, IReadOnlyList applicationExecutedList) { } - void OnCommit(Block block, StoreView snapshot) { } + void OnPersist(Block block, DataCache snapshot, IReadOnlyList applicationExecutedList) { } + void OnCommit(Block block, DataCache snapshot) { } bool ShouldThrowExceptionFromCommit(Exception ex) => false; } } diff --git a/src/neo/SmartContract/ApplicationEngine.Blockchain.cs b/src/neo/SmartContract/ApplicationEngine.Blockchain.cs deleted file mode 100644 index fef191fb44..0000000000 --- a/src/neo/SmartContract/ApplicationEngine.Blockchain.cs +++ /dev/null @@ -1,95 +0,0 @@ -using Neo.Ledger; -using Neo.Network.P2P.Payloads; -using Neo.Persistence; -using System; -using System.Numerics; - -namespace Neo.SmartContract -{ - partial class ApplicationEngine - { - public static readonly InteropDescriptor System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", nameof(GetBlockchainHeight), 1 << 4, CallFlags.ReadStates); - public static readonly InteropDescriptor System_Blockchain_GetBlock = Register("System.Blockchain.GetBlock", nameof(GetBlock), 1 << 16, CallFlags.ReadStates); - public static readonly InteropDescriptor System_Blockchain_GetTransaction = Register("System.Blockchain.GetTransaction", nameof(GetTransaction), 1 << 15, CallFlags.ReadStates); - public static readonly InteropDescriptor System_Blockchain_GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", nameof(GetTransactionHeight), 1 << 15, CallFlags.ReadStates); - public static readonly InteropDescriptor System_Blockchain_GetTransactionFromBlock = Register("System.Blockchain.GetTransactionFromBlock", nameof(GetTransactionFromBlock), 1 << 15, CallFlags.ReadStates); - - protected internal uint GetBlockchainHeight() - { - return Snapshot.Height; - } - - protected internal Block GetBlock(byte[] indexOrHash) - { - UInt256 hash; - if (indexOrHash.Length < UInt256.Length) - { - BigInteger bi = new BigInteger(indexOrHash); - if (bi < uint.MinValue || bi > uint.MaxValue) - throw new ArgumentOutOfRangeException(nameof(indexOrHash)); - hash = Blockchain.Singleton.GetBlockHash((uint)bi); - } - else if (indexOrHash.Length == UInt256.Length) - { - hash = new UInt256(indexOrHash); - } - else - { - throw new ArgumentException(); - } - if (hash is null) return null; - Block block = Snapshot.GetBlock(hash); - if (block is null) return null; - if (!IsTraceableBlock(Snapshot, block.Index)) return null; - return block; - } - - protected internal Transaction GetTransaction(UInt256 hash) - { - TransactionState state = Snapshot.Transactions.TryGet(hash); - if (state != null && !IsTraceableBlock(Snapshot, state.BlockIndex)) state = null; - return state?.Transaction; - } - - protected internal int GetTransactionHeight(UInt256 hash) - { - TransactionState state = Snapshot.Transactions.TryGet(hash); - if (state is null) return -1; - if (!IsTraceableBlock(Snapshot, state.BlockIndex)) return -1; - return (int)state.BlockIndex; - } - - protected internal Transaction GetTransactionFromBlock(byte[] blockIndexOrHash, int txIndex) - { - UInt256 hash; - if (blockIndexOrHash.Length < UInt256.Length) - { - BigInteger bi = new BigInteger(blockIndexOrHash); - if (bi < uint.MinValue || bi > uint.MaxValue) - throw new ArgumentOutOfRangeException(nameof(blockIndexOrHash)); - hash = Blockchain.Singleton.GetBlockHash((uint)bi); - } - else if (blockIndexOrHash.Length == UInt256.Length) - { - hash = new UInt256(blockIndexOrHash); - } - else - { - throw new ArgumentException(); - } - if (hash is null) return null; - TrimmedBlock block = Snapshot.Blocks.TryGet(hash); - if (block is null) return null; - if (!IsTraceableBlock(Snapshot, block.Index)) return null; - if (txIndex < 0 || txIndex >= block.Hashes.Length - 1) - throw new ArgumentOutOfRangeException(nameof(txIndex)); - return Snapshot.GetTransaction(block.Hashes[txIndex + 1]); - } - - private static bool IsTraceableBlock(StoreView snapshot, uint index) - { - if (index > snapshot.Height) return false; - return index + ProtocolSettings.Default.MaxTraceableBlocks > snapshot.Height; - } - } -} diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index e08a17099b..c52527bb6b 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -41,7 +41,7 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl protected internal void CallNativeContract(int id) { NativeContract contract = NativeContract.GetContract(id); - if (contract is null || contract.ActiveBlockIndex > Snapshot.Height) + if (contract is null || contract.ActiveBlockIndex > NativeContract.Ledger.CurrentIndex(Snapshot)) throw new InvalidOperationException(); contract.Invoke(this); } diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 8d74182e68..5a1edd1598 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -70,7 +70,7 @@ protected internal bool CheckWitnessInternal(UInt160 hash) else { OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id); - signers = Snapshot.GetTransaction(request.OriginalTxid).Signers; + signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid).Signers; } Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); if (signer is null) return false; diff --git a/src/neo/SmartContract/ApplicationEngine.Storage.cs b/src/neo/SmartContract/ApplicationEngine.Storage.cs index 24a7f5d2eb..17b62fba63 100644 --- a/src/neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/neo/SmartContract/ApplicationEngine.Storage.cs @@ -1,4 +1,3 @@ -using Neo.Ledger; using Neo.SmartContract.Iterators; using Neo.SmartContract.Native; using System; @@ -53,7 +52,7 @@ protected internal StorageContext AsReadOnly(StorageContext context) protected internal byte[] Get(StorageContext context, byte[] key) { - return Snapshot.Storages.TryGet(new StorageKey + return Snapshot.TryGet(new StorageKey { Id = context.Id, Key = key.ToArray() @@ -73,7 +72,7 @@ protected internal IIterator Find(StorageContext context, byte[] prefix, FindOpt if ((options.HasFlag(FindOptions.PickField0) || options.HasFlag(FindOptions.PickField1)) && !options.HasFlag(FindOptions.DeserializeValues)) throw new ArgumentException(); byte[] prefix_key = StorageKey.CreateSearchPrefix(context.Id, prefix); - return new StorageIterator(Snapshot.Storages.Find(prefix_key).GetEnumerator(), options, ReferenceCounter); + return new StorageIterator(Snapshot.Find(prefix_key).GetEnumerator(), options, ReferenceCounter); } protected internal void Put(StorageContext context, byte[] key, byte[] value) @@ -97,11 +96,11 @@ private void PutExInternal(StorageContext context, byte[] key, byte[] value, Sto Id = context.Id, Key = key }; - StorageItem item = Snapshot.Storages.GetAndChange(skey); + StorageItem item = Snapshot.GetAndChange(skey); if (item is null) { newDataSize = key.Length + value.Length; - Snapshot.Storages.Add(skey, item = new StorageItem()); + Snapshot.Add(skey, item = new StorageItem()); } else { @@ -128,9 +127,9 @@ protected internal void Delete(StorageContext context, byte[] key) Id = context.Id, Key = key }; - if (Snapshot.Storages.TryGet(skey)?.IsConstant == true) + if (Snapshot.TryGet(skey)?.IsConstant == true) throw new InvalidOperationException(); - Snapshot.Storages.Delete(skey); + Snapshot.Delete(skey); } } } diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 117ddfb059..936eaac7f6 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -42,7 +42,7 @@ public partial class ApplicationEngine : ExecutionEngine private List Disposables => disposables ??= new List(); public TriggerType Trigger { get; } public IVerifiable ScriptContainer { get; } - public StoreView Snapshot { get; } + public DataCache Snapshot { get; } public Block PersistingBlock { get; } public long GasConsumed { get; private set; } = 0; public long GasLeft => gas_amount - GasConsumed; @@ -52,7 +52,7 @@ public partial class ApplicationEngine : ExecutionEngine public UInt160 EntryScriptHash => EntryContext?.GetScriptHash(); public IReadOnlyList Notifications => notifications ?? (IReadOnlyList)Array.Empty(); - protected ApplicationEngine(TriggerType trigger, IVerifiable container, StoreView snapshot, Block persistingBlock, long gas) + protected ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, long gas) { this.Trigger = trigger; this.ScriptContainer = container; @@ -146,7 +146,7 @@ internal T CallFromNativeContract(UInt160 callingScriptHash, UInt160 hash, st return (T)Convert(Pop(), new InteropParameterDescriptor(typeof(T))); } - public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, Block persistingBlock = null, long gas = TestModeGas) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, long gas = TestModeGas) { return applicationEngineProvider?.Create(trigger, container, snapshot, persistingBlock, gas) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, gas); @@ -318,16 +318,17 @@ internal void StepOut() throw new InvalidOperationException("StepOut failed.", FaultException); } - private static Block CreateDummyBlock(StoreView snapshot) + private static Block CreateDummyBlock(DataCache snapshot) { - var currentBlock = snapshot.Blocks[snapshot.CurrentBlockHash]; + UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); + var currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash); return new Block { Version = 0, - PrevHash = snapshot.CurrentBlockHash, + PrevHash = hash, MerkleRoot = new UInt256(), Timestamp = currentBlock.Timestamp + Blockchain.MillisecondsPerBlock, - Index = snapshot.Height + 1, + Index = currentBlock.Index + 1, NextConsensus = currentBlock.NextConsensus, Witness = new Witness { @@ -354,9 +355,9 @@ internal static void ResetApplicationEngineProvider() Exchange(ref applicationEngineProvider, null); } - public static ApplicationEngine Run(byte[] script, StoreView snapshot = null, IVerifiable container = null, Block persistingBlock = null, int offset = 0, long gas = TestModeGas) + public static ApplicationEngine Run(byte[] script, DataCache snapshot = null, IVerifiable container = null, Block persistingBlock = null, int offset = 0, long gas = TestModeGas) { - SnapshotView disposable = null; + SnapshotCache disposable = null; if (snapshot is null) { disposable = Blockchain.Singleton.GetSnapshot(); diff --git a/src/neo/SmartContract/Contract.cs b/src/neo/SmartContract/Contract.cs index ca5a27b945..13246faf8b 100644 --- a/src/neo/SmartContract/Contract.cs +++ b/src/neo/SmartContract/Contract.cs @@ -106,5 +106,10 @@ public static byte[] CreateSignatureRedeemScript(ECPoint publicKey) return sb.ToArray(); } } + + public static UInt160 GetBFTAddress(ECPoint[] pubkeys) + { + return CreateMultiSigRedeemScript(pubkeys.Length - (pubkeys.Length - 1) / 3, pubkeys).ToScriptHash(); + } } } diff --git a/src/neo/SmartContract/ContractParametersContext.cs b/src/neo/SmartContract/ContractParametersContext.cs index 0b2a3a5447..40d44b424e 100644 --- a/src/neo/SmartContract/ContractParametersContext.cs +++ b/src/neo/SmartContract/ContractParametersContext.cs @@ -93,7 +93,7 @@ public IReadOnlyList ScriptHashes return _ScriptHashes; } - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) { _ScriptHashes = Verifiable.GetScriptHashesForVerifying(snapshot); } diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index e10c076829..5f0e076c4e 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -153,7 +153,7 @@ public static UInt160 ToScriptHash(this ReadOnlySpan script) return new UInt160(Crypto.Hash160(script)); } - public static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas) + public static bool VerifyWitnesses(this IVerifiable verifiable, DataCache snapshot, long gas) { if (gas < 0) return false; if (gas > MaxVerificationGas) gas = MaxVerificationGas; @@ -177,10 +177,10 @@ public static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapsh return true; } - internal static bool VerifyWitness(this IVerifiable verifiable, StoreView snapshot, UInt160 hash, Witness witness, long gas, out long fee) + internal static bool VerifyWitness(this IVerifiable verifiable, DataCache snapshot, UInt160 hash, Witness witness, long gas, out long fee) { fee = 0; - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.Clone(), null, gas)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, gas)) { CallFlags callFlags = !witness.VerificationScript.IsStandardContract() ? CallFlags.ReadStates : CallFlags.None; byte[] verification = witness.VerificationScript; diff --git a/src/neo/SmartContract/Native/ContractManagement.cs b/src/neo/SmartContract/Native/ContractManagement.cs index 4d6697c8b3..2bf9bd9231 100644 --- a/src/neo/SmartContract/Native/ContractManagement.cs +++ b/src/neo/SmartContract/Native/ContractManagement.cs @@ -1,7 +1,6 @@ #pragma warning disable IDE0051 using Neo.IO; -using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract.Manifest; @@ -64,9 +63,9 @@ internal ContractManagement() Manifest.Abi.Events = events.ToArray(); } - private int GetNextAvailableId(StoreView snapshot) + private int GetNextAvailableId(DataCache snapshot) { - StorageItem item = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_NextAvailableId), () => new StorageItem(1)); + StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId), () => new StorageItem(1)); int value = (int)(BigInteger)item; item.Add(1); return value; @@ -74,7 +73,7 @@ private int GetNextAvailableId(StoreView snapshot) internal override void Initialize(ApplicationEngine engine) { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_MinimumDeploymentFee), new StorageItem(10_00000000)); + engine.Snapshot.Add(CreateStorageKey(Prefix_MinimumDeploymentFee), new StorageItem(10_00000000)); } internal override void OnPersist(ApplicationEngine engine) @@ -83,7 +82,7 @@ internal override void OnPersist(ApplicationEngine engine) { if (contract.ActiveBlockIndex != engine.PersistingBlock.Index) continue; - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState + engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState { Id = contract.Id, Nef = contract.Nef, @@ -95,9 +94,9 @@ internal override void OnPersist(ApplicationEngine engine) } [ContractMethod(0_01000000, CallFlags.ReadStates)] - private long GetMinimumDeploymentFee(StoreView snapshot) + private long GetMinimumDeploymentFee(DataCache snapshot) { - return (long)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_MinimumDeploymentFee)]; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_MinimumDeploymentFee)]; } [ContractMethod(0_03000000, CallFlags.WriteStates)] @@ -105,19 +104,19 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) { if (value < 0) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee)).Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee)).Set(value); } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public ContractState GetContract(StoreView snapshot, UInt160 hash) + public ContractState GetContract(DataCache snapshot, UInt160 hash) { - return snapshot.Storages.TryGet(CreateStorageKey(Prefix_Contract).Add(hash))?.GetInteroperable(); + return snapshot.TryGet(CreateStorageKey(Prefix_Contract).Add(hash))?.GetInteroperable(); } - public IEnumerable ListContracts(StoreView snapshot) + public IEnumerable ListContracts(DataCache snapshot) { byte[] listContractsPrefix = CreateStorageKey(Prefix_Contract).ToArray(); - return snapshot.Storages.Find(listContractsPrefix).Select(kvp => kvp.Value.GetInteroperable()); + return snapshot.Find(listContractsPrefix).Select(kvp => kvp.Value.GetInteroperable()); } [ContractMethod(0, CallFlags.WriteStates | CallFlags.AllowNotify)] @@ -145,7 +144,7 @@ private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] ma ContractManifest parsedManifest = ContractManifest.Parse(manifest); UInt160 hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name); StorageKey key = CreateStorageKey(Prefix_Contract).Add(hash); - if (engine.Snapshot.Storages.Contains(key)) + if (engine.Snapshot.Contains(key)) throw new InvalidOperationException($"Contract Already Exists: {hash}"); ContractState contract = new ContractState { @@ -158,7 +157,7 @@ private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] ma if (!contract.Manifest.IsValid(hash)) throw new InvalidOperationException($"Invalid Manifest Hash: {hash}"); - engine.Snapshot.Storages.Add(key, new StorageItem(contract)); + engine.Snapshot.Add(key, new StorageItem(contract)); // Execute _deploy @@ -184,7 +183,7 @@ private void Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest, S engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); - var contract = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); + var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); if (nefFile != null) @@ -221,11 +220,11 @@ private void Destroy(ApplicationEngine engine) { UInt160 hash = engine.CallingScriptHash; StorageKey ckey = CreateStorageKey(Prefix_Contract).Add(hash); - ContractState contract = engine.Snapshot.Storages.TryGet(ckey)?.GetInteroperable(); + ContractState contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); if (contract is null) return; - engine.Snapshot.Storages.Delete(ckey); - foreach (var (key, _) in engine.Snapshot.Storages.Find(BitConverter.GetBytes(contract.Id))) - engine.Snapshot.Storages.Delete(key); + engine.Snapshot.Delete(ckey); + foreach (var (key, _) in engine.Snapshot.Find(BitConverter.GetBytes(contract.Id))) + engine.Snapshot.Delete(key); engine.SendNotification(Hash, "Destroy", new VM.Types.Array { hash.ToArray() }); } } diff --git a/src/neo/SmartContract/Native/ContractMethodMetadata.cs b/src/neo/SmartContract/Native/ContractMethodMetadata.cs index 563040721e..ffe7b7f3e3 100644 --- a/src/neo/SmartContract/Native/ContractMethodMetadata.cs +++ b/src/neo/SmartContract/Native/ContractMethodMetadata.cs @@ -28,7 +28,7 @@ public ContractMethodMetadata(MemberInfo member, ContractMethodAttribute attribu if (parameterInfos.Length > 0) { NeedApplicationEngine = parameterInfos[0].ParameterType.IsAssignableFrom(typeof(ApplicationEngine)); - NeedSnapshot = parameterInfos[0].ParameterType.IsAssignableFrom(typeof(StoreView)); + NeedSnapshot = parameterInfos[0].ParameterType.IsAssignableFrom(typeof(DataCache)); } if (NeedApplicationEngine || NeedSnapshot) this.Parameters = parameterInfos.Skip(1).Select(p => new InteropParameterDescriptor(p)).ToArray(); diff --git a/src/neo/SmartContract/Native/FungibleToken.cs b/src/neo/SmartContract/Native/FungibleToken.cs index 3e000c61b7..fa0e9d446a 100644 --- a/src/neo/SmartContract/Native/FungibleToken.cs +++ b/src/neo/SmartContract/Native/FungibleToken.cs @@ -1,5 +1,4 @@ using Neo.IO; -using Neo.Ledger; using Neo.Persistence; using Neo.SmartContract.Manifest; using Neo.VM.Types; @@ -61,11 +60,11 @@ internal protected virtual void Mint(ApplicationEngine engine, UInt160 account, { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())); TState state = storage.GetInteroperable(); OnBalanceChanging(engine, account, state, amount); state.Balance += amount; - storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)); + storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)); storage.Add(amount); PostTransfer(engine, null, account, amount, StackItem.Null, callOnPayment); } @@ -75,31 +74,31 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; StorageKey key = CreateStorageKey(Prefix_Account).Add(account); - StorageItem storage = engine.Snapshot.Storages.GetAndChange(key); + StorageItem storage = engine.Snapshot.GetAndChange(key); TState state = storage.GetInteroperable(); if (state.Balance < amount) throw new InvalidOperationException(); OnBalanceChanging(engine, account, state, -amount); if (state.Balance == amount) - engine.Snapshot.Storages.Delete(key); + engine.Snapshot.Delete(key); else state.Balance -= amount; - storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); + storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); storage.Add(-amount); PostTransfer(engine, account, null, amount, StackItem.Null, false); } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public virtual BigInteger TotalSupply(StoreView snapshot) + public virtual BigInteger TotalSupply(DataCache snapshot) { - StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_TotalSupply)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); if (storage is null) return BigInteger.Zero; return storage; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account) + public virtual BigInteger BalanceOf(DataCache snapshot, UInt160 account) { - StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; return storage.GetInteroperable().Balance; } @@ -111,7 +110,7 @@ protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 if (!from.Equals(engine.CallingScriptHash) && !engine.CheckWitnessInternal(from)) return false; StorageKey key_from = CreateStorageKey(Prefix_Account).Add(from); - StorageItem storage_from = engine.Snapshot.Storages.GetAndChange(key_from); + StorageItem storage_from = engine.Snapshot.GetAndChange(key_from); if (amount.IsZero) { if (storage_from != null) @@ -133,11 +132,11 @@ protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 { OnBalanceChanging(engine, from, state_from, -amount); if (state_from.Balance == amount) - engine.Snapshot.Storages.Delete(key_from); + engine.Snapshot.Delete(key_from); else state_from.Balance -= amount; StorageKey key_to = CreateStorageKey(Prefix_Account).Add(to); - StorageItem storage_to = engine.Snapshot.Storages.GetAndChange(key_to, () => new StorageItem(new TState())); + StorageItem storage_to = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new TState())); TState state_to = storage_to.GetInteroperable(); OnBalanceChanging(engine, to, state_to, amount); state_to.Balance += amount; diff --git a/src/neo/SmartContract/Native/GasToken.cs b/src/neo/SmartContract/Native/GasToken.cs index 81e61b666c..a8d51122f7 100644 --- a/src/neo/SmartContract/Native/GasToken.cs +++ b/src/neo/SmartContract/Native/GasToken.cs @@ -15,7 +15,7 @@ internal GasToken() internal override void Initialize(ApplicationEngine engine) { - UInt160 account = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators); + UInt160 account = Contract.GetBFTAddress(Blockchain.StandbyValidators); Mint(engine, account, 30_000_000 * Factor, false); } diff --git a/src/neo/SmartContract/Native/HashIndexState.cs b/src/neo/SmartContract/Native/HashIndexState.cs new file mode 100644 index 0000000000..c2bcb9831c --- /dev/null +++ b/src/neo/SmartContract/Native/HashIndexState.cs @@ -0,0 +1,24 @@ +using Neo.IO; +using Neo.VM; +using Neo.VM.Types; + +namespace Neo.SmartContract.Native +{ + class HashIndexState : IInteroperable + { + public UInt256 Hash; + public uint Index; + + void IInteroperable.FromStackItem(StackItem stackItem) + { + Struct @struct = (Struct)stackItem; + Hash = new UInt256(@struct[0].GetSpan()); + Index = (uint)@struct[1].GetInteger(); + } + + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + { + return new Struct(referenceCounter) { Hash.ToArray(), Index }; + } + } +} diff --git a/src/neo/SmartContract/Native/LedgerContract.cs b/src/neo/SmartContract/Native/LedgerContract.cs new file mode 100644 index 0000000000..2658584c7f --- /dev/null +++ b/src/neo/SmartContract/Native/LedgerContract.cs @@ -0,0 +1,205 @@ +#pragma warning disable IDE0051 + +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using System; +using System.Linq; +using System.Numerics; + +namespace Neo.SmartContract.Native +{ + public sealed class LedgerContract : NativeContract + { + private const byte Prefix_BlockHash = 9; + private const byte Prefix_CurrentBlock = 12; + private const byte Prefix_Block = 5; + private const byte Prefix_Transaction = 11; + + internal LedgerContract() + { + } + + internal override void OnPersist(ApplicationEngine engine) + { + engine.Snapshot.Add(CreateStorageKey(Prefix_BlockHash).AddBigEndian(engine.PersistingBlock.Index), new StorageItem(engine.PersistingBlock.Hash.ToArray(), true)); + engine.Snapshot.Add(CreateStorageKey(Prefix_Block).Add(engine.PersistingBlock.Hash), new StorageItem(Trim(engine.PersistingBlock).ToArray(), true)); + foreach (Transaction tx in engine.PersistingBlock.Transactions) + { + engine.Snapshot.Add(CreateStorageKey(Prefix_Transaction).Add(tx.Hash), new StorageItem(new TransactionState + { + BlockIndex = engine.PersistingBlock.Index, + Transaction = tx + }, true)); + } + } + + internal override void PostPersist(ApplicationEngine engine) + { + HashIndexState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState())).GetInteroperable(); + state.Hash = engine.PersistingBlock.Hash; + state.Index = engine.PersistingBlock.Index; + } + + internal bool Initialized(DataCache snapshot) + { + return snapshot.Find(CreateStorageKey(Prefix_Block).ToArray()).Any(); + } + + private bool IsTraceableBlock(DataCache snapshot, uint index) + { + uint currentIndex = CurrentIndex(snapshot); + if (index > currentIndex) return false; + return index + ProtocolSettings.Default.MaxTraceableBlocks > currentIndex; + } + + public UInt256 GetBlockHash(DataCache snapshot, uint index) + { + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); + if (item is null) return null; + return new UInt256(item.Value); + } + + [ContractMethod(0_01000000, CallFlags.ReadStates)] + public UInt256 CurrentHash(DataCache snapshot) + { + return snapshot[CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable().Hash; + } + + [ContractMethod(0_01000000, CallFlags.ReadStates)] + public uint CurrentIndex(DataCache snapshot) + { + return snapshot[CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable().Index; + } + + public bool ContainsBlock(DataCache snapshot, UInt256 hash) + { + return snapshot.Contains(CreateStorageKey(Prefix_Block).Add(hash)); + } + + public bool ContainsTransaction(DataCache snapshot, UInt256 hash) + { + return snapshot.Contains(CreateStorageKey(Prefix_Transaction).Add(hash)); + } + + public TrimmedBlock GetTrimmedBlock(DataCache snapshot, UInt256 hash) + { + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); + if (item is null) return null; + return item.Value.AsSerializable(); + } + + [ContractMethod(0_01000000, CallFlags.ReadStates)] + private TrimmedBlock GetBlock(DataCache snapshot, byte[] indexOrHash) + { + UInt256 hash; + if (indexOrHash.Length < UInt256.Length) + hash = GetBlockHash(snapshot, (uint)new BigInteger(indexOrHash)); + else if (indexOrHash.Length == UInt256.Length) + hash = new UInt256(indexOrHash); + else + throw new ArgumentException(null, nameof(indexOrHash)); + if (hash is null) return null; + TrimmedBlock block = GetTrimmedBlock(snapshot, hash); + if (block is null || !IsTraceableBlock(snapshot, block.Index)) return null; + return block; + } + + public Block GetBlock(DataCache snapshot, UInt256 hash) + { + TrimmedBlock state = GetTrimmedBlock(snapshot, hash); + if (state is null) return null; + return new Block + { + Version = state.Version, + PrevHash = state.PrevHash, + MerkleRoot = state.MerkleRoot, + Timestamp = state.Timestamp, + Index = state.Index, + NextConsensus = state.NextConsensus, + Witness = state.Witness, + ConsensusData = state.ConsensusData, + Transactions = state.Hashes.Skip(1).Select(p => GetTransaction(snapshot, p)).ToArray() + }; + } + + public Block GetBlock(DataCache snapshot, uint index) + { + UInt256 hash = GetBlockHash(snapshot, index); + if (hash is null) return null; + return GetBlock(snapshot, hash); + } + + public Header GetHeader(DataCache snapshot, UInt256 hash) + { + return GetTrimmedBlock(snapshot, hash)?.Header; + } + + public Header GetHeader(DataCache snapshot, uint index) + { + UInt256 hash = GetBlockHash(snapshot, index); + if (hash is null) return null; + return GetHeader(snapshot, hash); + } + + public TransactionState GetTransactionState(DataCache snapshot, UInt256 hash) + { + return snapshot.TryGet(CreateStorageKey(Prefix_Transaction).Add(hash))?.GetInteroperable(); + } + + public Transaction GetTransaction(DataCache snapshot, UInt256 hash) + { + return GetTransactionState(snapshot, hash)?.Transaction; + } + + [ContractMethod(0_01000000, CallFlags.ReadStates, Name = "getTransaction")] + private Transaction GetTransactionForContract(DataCache snapshot, UInt256 hash) + { + TransactionState state = GetTransactionState(snapshot, hash); + if (state is null || !IsTraceableBlock(snapshot, state.BlockIndex)) return null; + return state.Transaction; + } + + [ContractMethod(0_01000000, CallFlags.ReadStates)] + private int GetTransactionHeight(DataCache snapshot, UInt256 hash) + { + TransactionState state = GetTransactionState(snapshot, hash); + if (state is null || !IsTraceableBlock(snapshot, state.BlockIndex)) return -1; + return (int)state.BlockIndex; + } + + [ContractMethod(0_02000000, CallFlags.ReadStates)] + private Transaction GetTransactionFromBlock(DataCache snapshot, byte[] blockIndexOrHash, int txIndex) + { + UInt256 hash; + if (blockIndexOrHash.Length < UInt256.Length) + hash = GetBlockHash(snapshot, (uint)new BigInteger(blockIndexOrHash)); + else if (blockIndexOrHash.Length == UInt256.Length) + hash = new UInt256(blockIndexOrHash); + else + throw new ArgumentException(null, nameof(blockIndexOrHash)); + if (hash is null) return null; + TrimmedBlock block = GetTrimmedBlock(snapshot, hash); + if (block is null || !IsTraceableBlock(snapshot, block.Index)) return null; + if (txIndex < 0 || txIndex >= block.Hashes.Length - 1) + throw new ArgumentOutOfRangeException(nameof(txIndex)); + return GetTransaction(snapshot, block.Hashes[txIndex + 1]); + } + + private static TrimmedBlock Trim(Block block) + { + return new TrimmedBlock + { + Version = block.Version, + PrevHash = block.PrevHash, + MerkleRoot = block.MerkleRoot, + Timestamp = block.Timestamp, + Index = block.Index, + NextConsensus = block.NextConsensus, + Witness = block.Witness, + Hashes = block.Transactions.Select(p => p.Hash).Prepend(block.ConsensusData.Hash).ToArray(), + ConsensusData = block.ConsensusData + }; + } + } +} diff --git a/src/neo/SmartContract/Native/NameService.cs b/src/neo/SmartContract/Native/NameService.cs index 409e0fe8bb..0c4463157d 100644 --- a/src/neo/SmartContract/Native/NameService.cs +++ b/src/neo/SmartContract/Native/NameService.cs @@ -2,7 +2,6 @@ using Neo.Cryptography; using Neo.IO; -using Neo.Ledger; using Neo.Persistence; using Neo.VM; using Neo.VM.Types; @@ -35,7 +34,7 @@ internal NameService() internal override void Initialize(ApplicationEngine engine) { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_DomainPrice), new StorageItem(10_00000000)); + engine.Snapshot.Add(CreateStorageKey(Prefix_DomainPrice), new StorageItem(10_00000000)); } internal override void OnPersist(ApplicationEngine engine) @@ -43,11 +42,11 @@ internal override void OnPersist(ApplicationEngine engine) uint now = (uint)(engine.PersistingBlock.Timestamp / 1000) + 1; byte[] start = CreateStorageKey(Prefix_Expiration).AddBigEndian(0).ToArray(); byte[] end = CreateStorageKey(Prefix_Expiration).AddBigEndian(now).ToArray(); - foreach (var (key, _) in engine.Snapshot.Storages.FindRange(start, end)) + foreach (var (key, _) in engine.Snapshot.FindRange(start, end)) { - engine.Snapshot.Storages.Delete(key); - foreach (var (key2, _) in engine.Snapshot.Storages.Find(CreateStorageKey(Prefix_Record).Add(key.Key.AsSpan(5)).ToArray())) - engine.Snapshot.Storages.Delete(key2); + engine.Snapshot.Delete(key); + foreach (var (key2, _) in engine.Snapshot.Find(CreateStorageKey(Prefix_Record).Add(key.Key.AsSpan(5)).ToArray())) + engine.Snapshot.Delete(key2); Burn(engine, CreateStorageKey(Prefix_Token).Add(key.Key.AsSpan(5))); } } @@ -67,15 +66,15 @@ private void AddRoot(ApplicationEngine engine, string root) { if (!rootRegex.IsMatch(root)) throw new ArgumentException(null, nameof(root)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - StringList roots = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Roots), () => new StorageItem(new StringList())).GetInteroperable(); + StringList roots = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Roots), () => new StorageItem(new StringList())).GetInteroperable(); int index = roots.BinarySearch(root); if (index >= 0) throw new InvalidOperationException("The name already exists."); roots.Insert(~index, root); } - public IEnumerable GetRoots(StoreView snapshot) + public IEnumerable GetRoots(DataCache snapshot) { - return snapshot.Storages.TryGet(CreateStorageKey(Prefix_Roots))?.GetInteroperable() ?? Enumerable.Empty(); + return snapshot.TryGet(CreateStorageKey(Prefix_Roots))?.GetInteroperable() ?? Enumerable.Empty(); } [ContractMethod(0_03000000, CallFlags.WriteStates)] @@ -83,24 +82,24 @@ private void SetPrice(ApplicationEngine engine, long price) { if (price <= 0 || price > 10000_00000000) throw new ArgumentOutOfRangeException(nameof(price)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_DomainPrice)).Set(price); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_DomainPrice)).Set(price); } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public long GetPrice(StoreView snapshot) + public long GetPrice(DataCache snapshot) { - return (long)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_DomainPrice)]; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_DomainPrice)]; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public bool IsAvailable(StoreView snapshot, string name) + public bool IsAvailable(DataCache snapshot, string name) { if (!nameRegex.IsMatch(name)) throw new ArgumentException(null, nameof(name)); string[] names = name.Split('.'); if (names.Length != 2) throw new ArgumentException(null, nameof(name)); byte[] hash = GetKey(Utility.StrictUTF8.GetBytes(name)); - if (snapshot.Storages.TryGet(CreateStorageKey(Prefix_Token).Add(hash)) is not null) return false; - StringList roots = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Roots))?.GetInteroperable(); + if (snapshot.TryGet(CreateStorageKey(Prefix_Token).Add(hash)) is not null) return false; + StringList roots = snapshot.TryGet(CreateStorageKey(Prefix_Roots))?.GetInteroperable(); if (roots is null || roots.BinarySearch(names[1]) < 0) throw new InvalidOperationException(); return true; } @@ -113,8 +112,8 @@ private bool Register(ApplicationEngine engine, string name, UInt160 owner) if (names.Length != 2) throw new ArgumentException(null, nameof(name)); if (!engine.CheckWitnessInternal(owner)) throw new InvalidOperationException(); byte[] hash = GetKey(Utility.StrictUTF8.GetBytes(name)); - if (engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Token).Add(hash)) is not null) return false; - StringList roots = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Roots))?.GetInteroperable(); + if (engine.Snapshot.TryGet(CreateStorageKey(Prefix_Token).Add(hash)) is not null) return false; + StringList roots = engine.Snapshot.TryGet(CreateStorageKey(Prefix_Roots))?.GetInteroperable(); if (roots is null || roots.BinarySearch(names[1]) < 0) throw new InvalidOperationException(); engine.AddGas(GetPrice(engine.Snapshot)); NameState state = new NameState @@ -125,7 +124,7 @@ private bool Register(ApplicationEngine engine, string name, UInt160 owner) Expiration = (uint)(engine.PersistingBlock.Timestamp / 1000) + OneYear }; Mint(engine, state); - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash), new StorageItem(new byte[] { 0 })); + engine.Snapshot.Add(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash), new StorageItem(new byte[] { 0 })); return true; } @@ -137,10 +136,10 @@ private uint Renew(ApplicationEngine engine, string name) if (names.Length != 2) throw new ArgumentException(null, nameof(name)); engine.AddGas(GetPrice(engine.Snapshot)); byte[] hash = GetKey(Utility.StrictUTF8.GetBytes(name)); - NameState state = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Token).Add(hash)).GetInteroperable(); - engine.Snapshot.Storages.Delete(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash)); + NameState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Token).Add(hash)).GetInteroperable(); + engine.Snapshot.Delete(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash)); state.Expiration += OneYear; - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash), new StorageItem(new byte[] { 0 })); + engine.Snapshot.Add(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash), new StorageItem(new byte[] { 0 })); return state.Expiration; } @@ -151,7 +150,7 @@ private void SetAdmin(ApplicationEngine engine, string name, UInt160 admin) string[] names = name.Split('.'); if (names.Length != 2) throw new ArgumentException(null, nameof(name)); if (admin != null && !engine.CheckWitnessInternal(admin)) throw new InvalidOperationException(); - NameState state = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Token).Add(GetKey(Utility.StrictUTF8.GetBytes(name)))).GetInteroperable(); + NameState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Token).Add(GetKey(Utility.StrictUTF8.GetBytes(name)))).GetInteroperable(); if (!engine.CheckWitnessInternal(state.Owner)) throw new InvalidOperationException(); state.Admin = admin; } @@ -188,29 +187,29 @@ private void SetRecord(ApplicationEngine engine, string name, RecordType type, s } string domain = string.Join('.', name.Split('.')[^2..]); byte[] hash_domain = GetKey(Utility.StrictUTF8.GetBytes(domain)); - NameState state = engine.Snapshot.Storages[CreateStorageKey(Prefix_Token).Add(hash_domain)].GetInteroperable(); + NameState state = engine.Snapshot[CreateStorageKey(Prefix_Token).Add(hash_domain)].GetInteroperable(); if (!CheckAdmin(engine, state)) throw new InvalidOperationException(); - StorageItem item = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).Add(type), () => new StorageItem()); + StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).Add(type), () => new StorageItem()); item.Value = Utility.StrictUTF8.GetBytes(data); } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public string GetRecord(StoreView snapshot, string name, RecordType type) + public string GetRecord(DataCache snapshot, string name, RecordType type) { if (!nameRegex.IsMatch(name)) throw new ArgumentException(null, nameof(name)); string domain = string.Join('.', name.Split('.')[^2..]); byte[] hash_domain = GetKey(Utility.StrictUTF8.GetBytes(domain)); - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).Add(type)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).Add(type)); if (item is null) return null; return Utility.StrictUTF8.GetString(item.Value); } - public IEnumerable<(RecordType Type, string Data)> GetRecords(StoreView snapshot, string name) + public IEnumerable<(RecordType Type, string Data)> GetRecords(DataCache snapshot, string name) { if (!nameRegex.IsMatch(name)) throw new ArgumentException(null, nameof(name)); string domain = string.Join('.', name.Split('.')[^2..]); byte[] hash_domain = GetKey(Utility.StrictUTF8.GetBytes(domain)); - foreach (var (key, value) in snapshot.Storages.Find(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).ToArray())) + foreach (var (key, value) in snapshot.Find(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).ToArray())) yield return ((RecordType)key.Key[^1], Utility.StrictUTF8.GetString(value.Value)); } @@ -220,18 +219,18 @@ private void DeleteRecord(ApplicationEngine engine, string name, RecordType type if (!nameRegex.IsMatch(name)) throw new ArgumentException(null, nameof(name)); string domain = string.Join('.', name.Split('.')[^2..]); byte[] hash_domain = GetKey(Utility.StrictUTF8.GetBytes(domain)); - NameState state = engine.Snapshot.Storages[CreateStorageKey(Prefix_Token).Add(hash_domain)].GetInteroperable(); + NameState state = engine.Snapshot[CreateStorageKey(Prefix_Token).Add(hash_domain)].GetInteroperable(); if (!CheckAdmin(engine, state)) throw new InvalidOperationException(); - engine.Snapshot.Storages.Delete(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).Add(type)); + engine.Snapshot.Delete(CreateStorageKey(Prefix_Record).Add(hash_domain).Add(GetKey(Utility.StrictUTF8.GetBytes(name))).Add(type)); } [ContractMethod(0_03000000, CallFlags.ReadStates)] - public string Resolve(StoreView snapshot, string name, RecordType type) + public string Resolve(DataCache snapshot, string name, RecordType type) { return Resolve(snapshot, name, type, 2); } - private string Resolve(StoreView snapshot, string name, RecordType type, int redirect) + private string Resolve(DataCache snapshot, string name, RecordType type, int redirect) { if (redirect < 0) throw new InvalidOperationException(); var dictionary = GetRecords(snapshot, name).ToDictionary(p => p.Type, p => p.Data); diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index f887e63d0e..4796d2a96a 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -21,6 +21,7 @@ public abstract class NativeContract #region Named Native Contracts public static ContractManagement ContractManagement { get; } = new ContractManagement(); + public static LedgerContract Ledger { get; } = new LedgerContract(); public static NeoToken NEO { get; } = new NeoToken(); public static GasToken GAS { get; } = new GasToken(); public static PolicyContract Policy { get; } = new PolicyContract(); diff --git a/src/neo/SmartContract/Native/NeoToken.cs b/src/neo/SmartContract/Native/NeoToken.cs index b95f8eae89..e050e16877 100644 --- a/src/neo/SmartContract/Native/NeoToken.cs +++ b/src/neo/SmartContract/Native/NeoToken.cs @@ -2,7 +2,6 @@ using Neo.Cryptography.ECC; using Neo.IO; -using Neo.IO.Caching; using Neo.Ledger; using Neo.Persistence; using Neo.VM; @@ -38,7 +37,7 @@ internal NeoToken() this.TotalAmount = 100000000 * Factor; } - public override BigInteger TotalSupply(StoreView snapshot) + public override BigInteger TotalSupply(DataCache snapshot) { return TotalAmount; } @@ -48,9 +47,9 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco DistributeGas(engine, account, state); if (amount.IsZero) return; if (state.VoteTo is null) return; - engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); - CandidateState candidate = engine.Snapshot.Storages.GetAndChange(key).GetInteroperable(); + CandidateState candidate = engine.Snapshot.GetAndChange(key).GetInteroperable(); candidate.Votes += amount; CheckCandidate(engine.Snapshot, state.VoteTo, candidate); } @@ -65,7 +64,7 @@ private void DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccount GAS.Mint(engine, account, gas, true); } - private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger value, uint start, uint end) + private BigInteger CalculateBonus(DataCache snapshot, ECPoint vote, BigInteger value, uint start, uint end) { if (value.IsZero || start >= end) return BigInteger.Zero; if (value.Sign < 0) throw new ArgumentOutOfRangeException(nameof(value)); @@ -75,17 +74,17 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).ToArray(); byte[] keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start).ToArray(); - (_, var item) = snapshot.Storages.FindRange(keyStart, border, SeekDirection.Backward).FirstOrDefault(); + (_, var item) = snapshot.FindRange(keyStart, border, SeekDirection.Backward).FirstOrDefault(); BigInteger startRewardPerNeo = item ?? BigInteger.Zero; byte[] keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end).ToArray(); - (_, item) = snapshot.Storages.FindRange(keyEnd, border, SeekDirection.Backward).FirstOrDefault(); + (_, item) = snapshot.FindRange(keyEnd, border, SeekDirection.Backward).FirstOrDefault(); BigInteger endRewardPerNeo = item ?? BigInteger.Zero; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } - private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value, uint start, uint end) + private BigInteger CalculateNeoHolderReward(DataCache snapshot, BigInteger value, uint start, uint end) { BigInteger sum = 0; foreach (var (index, gasPerBlock) in GetSortedGasRecords(snapshot, end - 1)) @@ -104,13 +103,13 @@ private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value return value * sum * NeoHolderRewardRatio / 100 / TotalAmount; } - private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState candidate) + private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState candidate) { if (!candidate.Registered && candidate.Votes.IsZero) { - foreach (var (rewardKey, _) in snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray()).ToArray()) - snapshot.Storages.Delete(rewardKey); - snapshot.Storages.Delete(CreateStorageKey(Prefix_Candidate).Add(pubkey)); + foreach (var (rewardKey, _) in snapshot.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray()).ToArray()) + snapshot.Delete(rewardKey); + snapshot.Delete(CreateStorageKey(Prefix_Candidate).Add(pubkey)); } } @@ -119,13 +118,13 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c internal override void Initialize(ApplicationEngine engine) { var cachedCommittee = new CachedCommittee(Blockchain.StandbyCommittee.Select(p => (p, BigInteger.Zero))); - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Committee), new StorageItem(cachedCommittee)); - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(new byte[0])); + engine.Snapshot.Add(CreateStorageKey(Prefix_Committee), new StorageItem(cachedCommittee)); + engine.Snapshot.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(new byte[0])); // Initialize economic parameters - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(0u), new StorageItem(5 * GAS.Factor)); - Mint(engine, Blockchain.GetConsensusAddress(Blockchain.StandbyValidators), TotalAmount, false); + engine.Snapshot.Add(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(0u), new StorageItem(5 * GAS.Factor)); + Mint(engine, Contract.GetBFTAddress(Blockchain.StandbyValidators), TotalAmount, false); } internal override void OnPersist(ApplicationEngine engine) @@ -133,7 +132,7 @@ internal override void OnPersist(ApplicationEngine engine) // Set next committee if (ShouldRefreshCommittee(engine.PersistingBlock.Index)) { - StorageItem storageItem = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Committee)); + StorageItem storageItem = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Committee)); var cachedCommittee = storageItem.GetInteroperable(); cachedCommittee.Clear(); cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot)); @@ -167,9 +166,9 @@ internal override void PostPersist(ApplicationEngine engine) BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / member.Votes; StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(member.PublicKey).AddBigEndian(engine.PersistingBlock.Index + 1); byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(member.PublicKey).ToArray(); - (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); + (_, var item) = engine.Snapshot.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); voterSumRewardPerNEO += (item ?? BigInteger.Zero); - engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); + engine.Snapshot.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); } } } @@ -183,29 +182,29 @@ private bool SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) if (!CheckCommittee(engine)) return false; uint index = engine.PersistingBlock.Index + 1; - StorageItem entry = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); + StorageItem entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); entry.Set(gasPerBlock); return true; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public BigInteger GetGasPerBlock(StoreView snapshot) + public BigInteger GetGasPerBlock(DataCache snapshot) { - return GetSortedGasRecords(snapshot, snapshot.Height + 1).First().GasPerBlock; + return GetSortedGasRecords(snapshot, Ledger.CurrentIndex(snapshot) + 1).First().GasPerBlock; } - private IEnumerable<(uint Index, BigInteger GasPerBlock)> GetSortedGasRecords(StoreView snapshot, uint end) + private IEnumerable<(uint Index, BigInteger GasPerBlock)> GetSortedGasRecords(DataCache snapshot, uint end) { byte[] key = CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(end).ToArray(); byte[] boundary = CreateStorageKey(Prefix_GasPerBlock).ToArray(); - return snapshot.Storages.FindRange(key, boundary, SeekDirection.Backward) + return snapshot.FindRange(key, boundary, SeekDirection.Backward) .Select(u => (BinaryPrimitives.ReadUInt32BigEndian(u.Key.Key.AsSpan(^sizeof(uint))), (BigInteger)u.Value)); } [ContractMethod(0_03000000, CallFlags.ReadStates)] - public BigInteger UnclaimedGas(StoreView snapshot, UInt160 account, uint end) + public BigInteger UnclaimedGas(DataCache snapshot, UInt160 account, uint end) { - StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; NeoAccountState state = storage.GetInteroperable(); return CalculateBonus(snapshot, state.VoteTo, state.Balance, state.BalanceHeight, end); @@ -217,7 +216,7 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem(new CandidateState())); + StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable(); state.Registered = true; return true; @@ -229,8 +228,8 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - if (engine.Snapshot.Storages.TryGet(key) is null) return true; - StorageItem item = engine.Snapshot.Storages.GetAndChange(key); + if (engine.Snapshot.TryGet(key) is null) return true; + StorageItem item = engine.Snapshot.GetAndChange(key); CandidateState state = item.GetInteroperable(); state.Registered = false; CheckCandidate(engine.Snapshot, pubkey, state); @@ -241,18 +240,18 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) return false; - NeoAccountState state_account = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); + NeoAccountState state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); if (state_account is null) return false; CandidateState validator_new = null; if (voteTo != null) { - validator_new = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable(); + validator_new = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable(); if (validator_new is null) return false; if (!validator_new.Registered) return false; } if (state_account.VoteTo is null ^ voteTo is null) { - StorageItem item = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)); + StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)); if (state_account.VoteTo is null) item.Add(state_account.Balance); else @@ -262,7 +261,7 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); - StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(key); + StorageItem storage_validator = engine.Snapshot.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; CheckCandidate(engine.Snapshot, state_account.VoteTo, state_validator); @@ -276,10 +275,10 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) } [ContractMethod(1_00000000, CallFlags.ReadStates)] - public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(StoreView snapshot) + public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(DataCache snapshot) { byte[] prefix_key = CreateStorageKey(Prefix_Candidate).ToArray(); - return snapshot.Storages.Find(prefix_key).Select(p => + return snapshot.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), p.Value.GetInteroperable() @@ -287,30 +286,30 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) } [ContractMethod(1_00000000, CallFlags.ReadStates)] - public ECPoint[] GetCommittee(StoreView snapshot) + public ECPoint[] GetCommittee(DataCache snapshot) { return GetCommitteeFromCache(snapshot).Select(p => p.PublicKey).OrderBy(p => p).ToArray(); } - public UInt160 GetCommitteeAddress(StoreView snapshot) + public UInt160 GetCommitteeAddress(DataCache snapshot) { ECPoint[] committees = GetCommittee(snapshot); return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); } - private CachedCommittee GetCommitteeFromCache(StoreView snapshot) + private CachedCommittee GetCommitteeFromCache(DataCache snapshot) { - return snapshot.Storages[CreateStorageKey(Prefix_Committee)].GetInteroperable(); + return snapshot[CreateStorageKey(Prefix_Committee)].GetInteroperable(); } - public ECPoint[] ComputeNextBlockValidators(StoreView snapshot) + public ECPoint[] ComputeNextBlockValidators(DataCache snapshot) { return ComputeCommitteeMembers(snapshot).Select(p => p.PublicKey).Take(ProtocolSettings.Default.ValidatorsCount).OrderBy(p => p).ToArray(); } - private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> ComputeCommitteeMembers(StoreView snapshot) + private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> ComputeCommitteeMembers(DataCache snapshot) { - decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; + decimal votersCount = (decimal)(BigInteger)snapshot[CreateStorageKey(Prefix_VotersCount)]; decimal voterTurnout = votersCount / (decimal)TotalAmount; var candidates = GetCandidates(snapshot); if (voterTurnout < EffectiveVoterTurnout || candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) @@ -319,7 +318,7 @@ public ECPoint[] ComputeNextBlockValidators(StoreView snapshot) } [ContractMethod(1_00000000, CallFlags.ReadStates)] - public ECPoint[] GetNextBlockValidators(StoreView snapshot) + public ECPoint[] GetNextBlockValidators(DataCache snapshot) { return GetCommitteeFromCache(snapshot) .Take(ProtocolSettings.Default.ValidatorsCount) diff --git a/src/neo/SmartContract/Native/NonfungibleToken.cs b/src/neo/SmartContract/Native/NonfungibleToken.cs index c77fbc70fe..8fa3696fe5 100644 --- a/src/neo/SmartContract/Native/NonfungibleToken.cs +++ b/src/neo/SmartContract/Native/NonfungibleToken.cs @@ -1,5 +1,4 @@ using Neo.IO; -using Neo.Ledger; using Neo.Persistence; using Neo.SmartContract.Iterators; using Neo.SmartContract.Manifest; @@ -65,10 +64,10 @@ protected NonfungibleToken() protected void Mint(ApplicationEngine engine, TokenState token) { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Token).Add(GetKey(token.Id)), new StorageItem(token)); - NFTAccountState account = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Account).Add(token.Owner), () => new StorageItem(new NFTAccountState())).GetInteroperable(); + engine.Snapshot.Add(CreateStorageKey(Prefix_Token).Add(GetKey(token.Id)), new StorageItem(token)); + NFTAccountState account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(token.Owner), () => new StorageItem(new NFTAccountState())).GetInteroperable(); account.Add(token.Id); - engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)).Add(1); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)).Add(1); PostTransfer(engine, null, token.Owner, token.Id); } @@ -79,55 +78,55 @@ protected void Burn(ApplicationEngine engine, byte[] tokenId) private protected void Burn(ApplicationEngine engine, StorageKey key) { - TokenState token = engine.Snapshot.Storages.TryGet(key)?.GetInteroperable(); + TokenState token = engine.Snapshot.TryGet(key)?.GetInteroperable(); if (token is null) throw new InvalidOperationException(); - engine.Snapshot.Storages.Delete(key); + engine.Snapshot.Delete(key); StorageKey key_account = CreateStorageKey(Prefix_Account).Add(token.Owner); - NFTAccountState account = engine.Snapshot.Storages.GetAndChange(key_account).GetInteroperable(); + NFTAccountState account = engine.Snapshot.GetAndChange(key_account).GetInteroperable(); account.Remove(token.Id); if (account.Balance.IsZero) - engine.Snapshot.Storages.Delete(key_account); - engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply)).Add(-1); + engine.Snapshot.Delete(key_account); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)).Add(-1); PostTransfer(engine, token.Owner, null, token.Id); } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public BigInteger TotalSupply(StoreView snapshot) + public BigInteger TotalSupply(DataCache snapshot) { - StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_TotalSupply)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); return storage ?? BigInteger.Zero; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public UInt160 OwnerOf(StoreView snapshot, byte[] tokenId) + public UInt160 OwnerOf(DataCache snapshot, byte[] tokenId) { - return snapshot.Storages[CreateStorageKey(Prefix_Token).Add(GetKey(tokenId))].GetInteroperable().Owner; + return snapshot[CreateStorageKey(Prefix_Token).Add(GetKey(tokenId))].GetInteroperable().Owner; } [ContractMethod(0_01000000, CallFlags.ReadStates)] public Map Properties(ApplicationEngine engine, byte[] tokenId) { - return engine.Snapshot.Storages[CreateStorageKey(Prefix_Token).Add(GetKey(tokenId))].GetInteroperable().ToMap(engine.ReferenceCounter); + return engine.Snapshot[CreateStorageKey(Prefix_Token).Add(GetKey(tokenId))].GetInteroperable().ToMap(engine.ReferenceCounter); } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public BigInteger BalanceOf(StoreView snapshot, UInt160 owner) + public BigInteger BalanceOf(DataCache snapshot, UInt160 owner) { if (owner is null) throw new ArgumentNullException(nameof(owner)); - return snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(owner))?.GetInteroperable().Balance ?? BigInteger.Zero; + return snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(owner))?.GetInteroperable().Balance ?? BigInteger.Zero; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public IIterator TokensOf(StoreView snapshot, UInt160 owner) + public IIterator TokensOf(DataCache snapshot, UInt160 owner) { if (owner is null) { - var results = snapshot.Storages.Find(new[] { Prefix_Token }).GetEnumerator(); + var results = snapshot.Find(new[] { Prefix_Token }).GetEnumerator(); return new StorageIterator(results, FindOptions.ValuesOnly | FindOptions.DeserializeValues | FindOptions.PickField1, null); } else { - NFTAccountState account = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(owner))?.GetInteroperable(); + NFTAccountState account = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(owner))?.GetInteroperable(); IReadOnlyList tokens = account?.Tokens ?? (IReadOnlyList)System.Array.Empty(); return new ArrayWrapper(tokens.Select(p => (StackItem)p).ToArray()); } @@ -138,21 +137,21 @@ protected bool Transfer(ApplicationEngine engine, UInt160 to, byte[] tokenId) { if (to is null) throw new ArgumentNullException(nameof(to)); StorageKey key_token = CreateStorageKey(Prefix_Token).Add(GetKey(tokenId)); - TokenState token = engine.Snapshot.Storages.TryGet(key_token)?.GetInteroperable(); + TokenState token = engine.Snapshot.TryGet(key_token)?.GetInteroperable(); UInt160 from = token.Owner; if (!from.Equals(engine.CallingScriptHash) && !engine.CheckWitnessInternal(from)) return false; if (!from.Equals(to)) { - token = engine.Snapshot.Storages.GetAndChange(key_token).GetInteroperable(); + token = engine.Snapshot.GetAndChange(key_token).GetInteroperable(); StorageKey key_from = CreateStorageKey(Prefix_Account).Add(from); - NFTAccountState account = engine.Snapshot.Storages.GetAndChange(key_from).GetInteroperable(); + NFTAccountState account = engine.Snapshot.GetAndChange(key_from).GetInteroperable(); account.Remove(tokenId); if (account.Balance.IsZero) - engine.Snapshot.Storages.Delete(key_from); + engine.Snapshot.Delete(key_from); token.Owner = to; StorageKey key_to = CreateStorageKey(Prefix_Account).Add(to); - account = engine.Snapshot.Storages.GetAndChange(key_to, () => new StorageItem(new NFTAccountState())).GetInteroperable(); + account = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new NFTAccountState())).GetInteroperable(); account.Add(tokenId); OnTransferred(engine, from, token); } diff --git a/src/neo/SmartContract/Native/OracleContract.cs b/src/neo/SmartContract/Native/OracleContract.cs index b660f347ff..5e4e710de0 100644 --- a/src/neo/SmartContract/Native/OracleContract.cs +++ b/src/neo/SmartContract/Native/OracleContract.cs @@ -2,7 +2,6 @@ using Neo.Cryptography; using Neo.IO; -using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract.Manifest; @@ -103,22 +102,22 @@ private UInt256 GetOriginalTxid(ApplicationEngine engine) return request.OriginalTxid; } - public OracleRequest GetRequest(StoreView snapshot, ulong id) + public OracleRequest GetRequest(DataCache snapshot, ulong id) { - return snapshot.Storages.TryGet(CreateStorageKey(Prefix_Request).Add(id))?.GetInteroperable(); + return snapshot.TryGet(CreateStorageKey(Prefix_Request).Add(id))?.GetInteroperable(); } - public IEnumerable<(ulong, OracleRequest)> GetRequests(StoreView snapshot) + public IEnumerable<(ulong, OracleRequest)> GetRequests(DataCache snapshot) { - return snapshot.Storages.Find(new KeyBuilder(Id, Prefix_Request).ToArray()).Select(p => (BitConverter.ToUInt64(p.Key.Key, 1), p.Value.GetInteroperable())); + return snapshot.Find(new KeyBuilder(Id, Prefix_Request).ToArray()).Select(p => (BitConverter.ToUInt64(p.Key.Key, 1), p.Value.GetInteroperable())); } - public IEnumerable<(ulong, OracleRequest)> GetRequestsByUrl(StoreView snapshot, string url) + public IEnumerable<(ulong, OracleRequest)> GetRequestsByUrl(DataCache snapshot, string url) { - IdList list = snapshot.Storages.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); + IdList list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); if (list is null) yield break; foreach (ulong id in list) - yield return (id, snapshot.Storages[CreateStorageKey(Prefix_Request).Add(id)].GetInteroperable()); + yield return (id, snapshot[CreateStorageKey(Prefix_Request).Add(id)].GetInteroperable()); } private static byte[] GetUrlHash(string url) @@ -128,7 +127,7 @@ private static byte[] GetUrlHash(string url) internal override void Initialize(ApplicationEngine engine) { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_RequestId), new StorageItem(BitConverter.GetBytes(0ul))); + engine.Snapshot.Add(CreateStorageKey(Prefix_RequestId), new StorageItem(BitConverter.GetBytes(0ul))); } internal override void PostPersist(ApplicationEngine engine) @@ -142,15 +141,15 @@ internal override void PostPersist(ApplicationEngine engine) //Remove the request from storage StorageKey key = CreateStorageKey(Prefix_Request).Add(response.Id); - OracleRequest request = engine.Snapshot.Storages.TryGet(key)?.GetInteroperable(); + OracleRequest request = engine.Snapshot.TryGet(key)?.GetInteroperable(); if (request == null) continue; - engine.Snapshot.Storages.Delete(key); + engine.Snapshot.Delete(key); //Remove the id from IdList key = CreateStorageKey(Prefix_IdList).Add(GetUrlHash(request.Url)); - IdList list = engine.Snapshot.Storages.GetAndChange(key).GetInteroperable(); + IdList list = engine.Snapshot.GetAndChange(key).GetInteroperable(); if (!list.Remove(response.Id)) throw new InvalidOperationException(); - if (list.Count == 0) engine.Snapshot.Storages.Delete(key); + if (list.Count == 0) engine.Snapshot.Delete(key); //Mint GAS for oracle nodes nodes ??= RoleManagement.GetDesignatedByRole(engine.Snapshot, Role.Oracle, engine.PersistingBlock.Index).Select(p => (Contract.CreateSignatureRedeemScript(p).ToScriptHash(), BigInteger.Zero)).ToArray(); @@ -184,14 +183,14 @@ private void Request(ApplicationEngine engine, string url, string filter, string GAS.Mint(engine, Hash, gasForResponse, false); //Increase the request id - StorageItem item_id = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_RequestId)); + StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId)); ulong id = BitConverter.ToUInt64(item_id.Value) + 1; item_id.Value = BitConverter.GetBytes(id); //Put the request to storage if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash) is null) throw new InvalidOperationException(); - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Request).Add(item_id.Value), new StorageItem(new OracleRequest + engine.Snapshot.Add(CreateStorageKey(Prefix_Request).Add(item_id.Value), new StorageItem(new OracleRequest { OriginalTxid = GetOriginalTxid(engine), GasForResponse = gasForResponse, @@ -203,7 +202,7 @@ private void Request(ApplicationEngine engine, string url, string filter, string })); //Add the id to the IdList - var list = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList())).GetInteroperable(); + var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList())).GetInteroperable(); if (list.Count >= 256) throw new InvalidOperationException("There are too many pending responses for this url"); list.Add(id); diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index c873f4ce14..0b5b7a20c3 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -1,6 +1,5 @@ #pragma warning disable IDE0051 -using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.Persistence; @@ -29,57 +28,57 @@ internal PolicyContract() } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public uint GetMaxTransactionsPerBlock(StoreView snapshot) + public uint GetMaxTransactionsPerBlock(DataCache snapshot) { - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxTransactionsPerBlock)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_MaxTransactionsPerBlock)); if (item is null) return 512; return (uint)(BigInteger)item; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public uint GetMaxBlockSize(StoreView snapshot) + public uint GetMaxBlockSize(DataCache snapshot) { - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxBlockSize)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_MaxBlockSize)); if (item is null) return 1024 * 256; return (uint)(BigInteger)item; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public long GetMaxBlockSystemFee(StoreView snapshot) + public long GetMaxBlockSystemFee(DataCache snapshot) { - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxBlockSystemFee)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_MaxBlockSystemFee)); if (item is null) return 9000 * (long)GAS.Factor; // For the transfer method of NEP5, the maximum persisting time is about three seconds. return (long)(BigInteger)item; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public long GetFeePerByte(StoreView snapshot) + public long GetFeePerByte(DataCache snapshot) { - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_FeePerByte)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_FeePerByte)); if (item is null) return 1000; return (long)(BigInteger)item; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public uint GetExecFeeFactor(StoreView snapshot) + public uint GetExecFeeFactor(DataCache snapshot) { - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_ExecFeeFactor)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_ExecFeeFactor)); if (item is null) return DefaultExecFeeFactor; return (uint)(BigInteger)item; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public uint GetStoragePrice(StoreView snapshot) + public uint GetStoragePrice(DataCache snapshot) { - StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_StoragePrice)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_StoragePrice)); if (item is null) return DefaultStoragePrice; return (uint)(BigInteger)item; } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public bool IsBlocked(StoreView snapshot, UInt160 account) + public bool IsBlocked(DataCache snapshot, UInt160 account) { - return snapshot.Storages.Contains(CreateStorageKey(Prefix_BlockedAccount).Add(account)); + return snapshot.Contains(CreateStorageKey(Prefix_BlockedAccount).Add(account)); } [ContractMethod(0_03000000, CallFlags.WriteStates)] @@ -87,7 +86,7 @@ private bool SetMaxBlockSize(ApplicationEngine engine, uint value) { if (value > Message.PayloadMaxSize) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) return false; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSize), () => new StorageItem()); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MaxBlockSize), () => new StorageItem()); storage.Set(value); return true; } @@ -97,7 +96,7 @@ private bool SetMaxTransactionsPerBlock(ApplicationEngine engine, uint value) { if (value > Block.MaxTransactionsPerBlock) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) return false; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxTransactionsPerBlock), () => new StorageItem()); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MaxTransactionsPerBlock), () => new StorageItem()); storage.Set(value); return true; } @@ -107,7 +106,7 @@ private bool SetMaxBlockSystemFee(ApplicationEngine engine, long value) { if (value <= 4007600) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) return false; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSystemFee), () => new StorageItem()); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MaxBlockSystemFee), () => new StorageItem()); storage.Set(value); return true; } @@ -117,7 +116,7 @@ private bool SetFeePerByte(ApplicationEngine engine, long value) { if (value < 0 || value > 1_00000000) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) return false; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_FeePerByte), () => new StorageItem()); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_FeePerByte), () => new StorageItem()); storage.Set(value); return true; } @@ -127,7 +126,7 @@ private bool SetExecFeeFactor(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxExecFeeFactor) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) return false; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor), () => new StorageItem()); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor), () => new StorageItem()); storage.Set(value); return true; } @@ -137,7 +136,7 @@ private bool SetStoragePrice(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxStoragePrice) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) return false; - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_StoragePrice), () => new StorageItem()); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_StoragePrice), () => new StorageItem()); storage.Set(value); return true; } @@ -148,9 +147,9 @@ private bool BlockAccount(ApplicationEngine engine, UInt160 account) if (!CheckCommittee(engine)) return false; var key = CreateStorageKey(Prefix_BlockedAccount).Add(account); - if (engine.Snapshot.Storages.Contains(key)) return false; + if (engine.Snapshot.Contains(key)) return false; - engine.Snapshot.Storages.Add(key, new StorageItem(new byte[] { 0x01 })); + engine.Snapshot.Add(key, new StorageItem(new byte[] { 0x01 })); return true; } @@ -160,9 +159,9 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account) if (!CheckCommittee(engine)) return false; var key = CreateStorageKey(Prefix_BlockedAccount).Add(account); - if (!engine.Snapshot.Storages.Contains(key)) return false; + if (!engine.Snapshot.Contains(key)) return false; - engine.Snapshot.Storages.Delete(key); + engine.Snapshot.Delete(key); return true; } } diff --git a/src/neo/SmartContract/Native/RoleManagement.cs b/src/neo/SmartContract/Native/RoleManagement.cs index ee95bd3edb..6c79093139 100644 --- a/src/neo/SmartContract/Native/RoleManagement.cs +++ b/src/neo/SmartContract/Native/RoleManagement.cs @@ -1,8 +1,6 @@ using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; -using Neo.IO.Caching; -using Neo.Ledger; using Neo.Persistence; using Neo.VM; using Neo.VM.Types; @@ -19,15 +17,15 @@ internal RoleManagement() } [ContractMethod(0_01000000, CallFlags.ReadStates)] - public ECPoint[] GetDesignatedByRole(StoreView snapshot, Role role, uint index) + public ECPoint[] GetDesignatedByRole(DataCache snapshot, Role role, uint index) { if (!Enum.IsDefined(typeof(Role), role)) throw new ArgumentOutOfRangeException(nameof(role)); - if (snapshot.Height + 1 < index) + if (Ledger.CurrentIndex(snapshot) + 1 < index) throw new ArgumentOutOfRangeException(nameof(index)); byte[] key = CreateStorageKey((byte)role).AddBigEndian(index).ToArray(); byte[] boundary = CreateStorageKey((byte)role).ToArray(); - return snapshot.Storages.FindRange(key, boundary, SeekDirection.Backward) + return snapshot.FindRange(key, boundary, SeekDirection.Backward) .Select(u => u.Value.GetInteroperable().ToArray()) .FirstOrDefault() ?? System.Array.Empty(); } @@ -45,12 +43,12 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node throw new InvalidOperationException(nameof(DesignateAsRole)); uint index = engine.PersistingBlock.Index + 1; var key = CreateStorageKey((byte)role).AddBigEndian(index); - if (engine.Snapshot.Storages.Contains(key)) + if (engine.Snapshot.Contains(key)) throw new InvalidOperationException(); NodeList list = new NodeList(); list.AddRange(nodes); list.Sort(); - engine.Snapshot.Storages.Add(key, new StorageItem(list)); + engine.Snapshot.Add(key, new StorageItem(list)); } private class NodeList : List, IInteroperable diff --git a/src/neo/SmartContract/Native/TransactionState.cs b/src/neo/SmartContract/Native/TransactionState.cs new file mode 100644 index 0000000000..671146a6de --- /dev/null +++ b/src/neo/SmartContract/Native/TransactionState.cs @@ -0,0 +1,29 @@ +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.VM; +using Neo.VM.Types; + +namespace Neo.SmartContract.Native +{ + public class TransactionState : IInteroperable + { + public uint BlockIndex; + public Transaction Transaction; + + private StackItem _rawTransaction; + + void IInteroperable.FromStackItem(StackItem stackItem) + { + Struct @struct = (Struct)stackItem; + BlockIndex = (uint)@struct[0].GetInteger(); + _rawTransaction = @struct[1]; + Transaction = _rawTransaction.GetSpan().AsSerializable(); + } + + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + { + _rawTransaction ??= Transaction.ToArray(); + return new Struct(referenceCounter) { BlockIndex, _rawTransaction }; + } + } +} diff --git a/src/neo/Ledger/TrimmedBlock.cs b/src/neo/SmartContract/Native/TrimmedBlock.cs similarity index 52% rename from src/neo/Ledger/TrimmedBlock.cs rename to src/neo/SmartContract/Native/TrimmedBlock.cs index 5b58e40246..11133fb9d7 100644 --- a/src/neo/Ledger/TrimmedBlock.cs +++ b/src/neo/SmartContract/Native/TrimmedBlock.cs @@ -1,35 +1,19 @@ using Neo.IO; -using Neo.IO.Caching; using Neo.IO.Json; using Neo.Network.P2P.Payloads; +using Neo.VM; +using Neo.VM.Types; +using System; using System.IO; using System.Linq; -namespace Neo.Ledger +namespace Neo.SmartContract.Native { - public class TrimmedBlock : BlockBase, ICloneable + public class TrimmedBlock : BlockBase, IInteroperable { public UInt256[] Hashes; public ConsensusData ConsensusData; - public bool IsBlock => Hashes.Length > 0; - - public Block GetBlock(DataCache cache) - { - return new Block - { - Version = Version, - PrevHash = PrevHash, - MerkleRoot = MerkleRoot, - Timestamp = Timestamp, - Index = Index, - NextConsensus = NextConsensus, - Witness = Witness, - ConsensusData = ConsensusData, - Transactions = Hashes.Skip(1).Select(p => cache[p].Transaction).ToArray() - }; - } - private Header _header = null; public Header Header { @@ -56,23 +40,6 @@ public Header Header + Hashes.GetVarSize() //Hashes + (ConsensusData?.Size ?? 0); //ConsensusData - TrimmedBlock ICloneable.Clone() - { - return new TrimmedBlock - { - Version = Version, - PrevHash = PrevHash, - MerkleRoot = MerkleRoot, - Timestamp = Timestamp, - Index = Index, - NextConsensus = NextConsensus, - Witness = Witness, - Hashes = Hashes, - ConsensusData = ConsensusData, - _header = _header - }; - } - public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); @@ -81,20 +48,6 @@ public override void Deserialize(BinaryReader reader) ConsensusData = reader.ReadSerializable(); } - void ICloneable.FromReplica(TrimmedBlock replica) - { - Version = replica.Version; - PrevHash = replica.PrevHash; - MerkleRoot = replica.MerkleRoot; - Timestamp = replica.Timestamp; - Index = replica.Index; - NextConsensus = replica.NextConsensus; - Witness = replica.Witness; - Hashes = replica.Hashes; - ConsensusData = replica.ConsensusData; - _header = replica._header; - } - public override void Serialize(BinaryWriter writer) { base.Serialize(writer); @@ -110,5 +63,30 @@ public override JObject ToJson() json["hashes"] = Hashes.Select(p => (JObject)p.ToString()).ToArray(); return json; } + + void IInteroperable.FromStackItem(StackItem stackItem) + { + throw new NotSupportedException(); + } + + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + { + return new VM.Types.Array(referenceCounter, new StackItem[] + { + // Computed properties + Hash.ToArray(), + + // BlockBase properties + Version, + PrevHash.ToArray(), + MerkleRoot.ToArray(), + Timestamp, + Index, + NextConsensus.ToArray(), + + // Block properties + Hashes.Length - 1 + }); + } } } diff --git a/src/neo/Ledger/StorageFlags.cs b/src/neo/SmartContract/StorageFlags.cs similarity index 81% rename from src/neo/Ledger/StorageFlags.cs rename to src/neo/SmartContract/StorageFlags.cs index cace3c97ef..5888426e66 100644 --- a/src/neo/Ledger/StorageFlags.cs +++ b/src/neo/SmartContract/StorageFlags.cs @@ -1,6 +1,6 @@ using System; -namespace Neo.Ledger +namespace Neo.SmartContract { [Flags] public enum StorageFlags : byte diff --git a/src/neo/Ledger/StorageItem.cs b/src/neo/SmartContract/StorageItem.cs similarity index 92% rename from src/neo/Ledger/StorageItem.cs rename to src/neo/SmartContract/StorageItem.cs index 7b8f99bec3..ff3d0d5bd1 100644 --- a/src/neo/Ledger/StorageItem.cs +++ b/src/neo/SmartContract/StorageItem.cs @@ -1,14 +1,13 @@ using Neo.IO; -using Neo.SmartContract; using Neo.VM; using System; using System.Collections.Generic; using System.IO; using System.Numerics; -namespace Neo.Ledger +namespace Neo.SmartContract { - public class StorageItem : ICloneable, ISerializable + public class StorageItem : ISerializable { private byte[] value; private object cache; @@ -61,7 +60,7 @@ public void Add(BigInteger integer) Set(this + integer); } - StorageItem ICloneable.Clone() + public StorageItem Clone() { return new StorageItem { @@ -76,7 +75,7 @@ public void Deserialize(BinaryReader reader) IsConstant = reader.ReadBoolean(); } - void ICloneable.FromReplica(StorageItem replica) + public void FromReplica(StorageItem replica) { Value = replica.Value; IsConstant = replica.IsConstant; diff --git a/src/neo/Ledger/StorageKey.cs b/src/neo/SmartContract/StorageKey.cs similarity index 98% rename from src/neo/Ledger/StorageKey.cs rename to src/neo/SmartContract/StorageKey.cs index 620f0d1fbd..99f4c0387c 100644 --- a/src/neo/Ledger/StorageKey.cs +++ b/src/neo/SmartContract/StorageKey.cs @@ -4,7 +4,7 @@ using System.Buffers.Binary; using System.IO; -namespace Neo.Ledger +namespace Neo.SmartContract { public class StorageKey : IEquatable, ISerializable { diff --git a/src/neo/Wallets/AssetDescriptor.cs b/src/neo/Wallets/AssetDescriptor.cs index 3be315f86d..7cbcbdc1a4 100644 --- a/src/neo/Wallets/AssetDescriptor.cs +++ b/src/neo/Wallets/AssetDescriptor.cs @@ -16,7 +16,7 @@ public class AssetDescriptor public AssetDescriptor(UInt160 asset_id) { - using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); + using SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot(); var contract = NativeContract.ContractManagement.GetContract(snapshot, asset_id); if (contract is null) throw new ArgumentException(); diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index 141b21eec7..d5c9ef0a13 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -252,7 +252,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null { accounts = new[] { from }; } - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) { Dictionary cosignerList = cosigners?.ToDictionary(p => p.Account) ?? new Dictionary(); byte[] script; @@ -323,14 +323,14 @@ public Transaction MakeTransaction(byte[] script, UInt160 sender = null, Signer[ { accounts = new[] { sender }; } - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) + using (SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot()) { var balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList(); return MakeTransaction(snapshot, script, cosigners ?? Array.Empty(), attributes ?? Array.Empty(), balances_gas); } } - private Transaction MakeTransaction(StoreView snapshot, byte[] script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas) + private Transaction MakeTransaction(DataCache snapshot, byte[] script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas) { Random rand = new Random(); foreach (var (account, value) in balances_gas) @@ -340,13 +340,13 @@ private Transaction MakeTransaction(StoreView snapshot, byte[] script, Signer[] Version = 0, Nonce = (uint)rand.Next(), Script = script, - ValidUntilBlock = snapshot.Height + Transaction.MaxValidUntilBlockIncrement, + ValidUntilBlock = NativeContract.Ledger.CurrentIndex(snapshot) + Transaction.MaxValidUntilBlockIncrement, Signers = GetSigners(account, cosigners), Attributes = attributes, }; // will try to execute 'transfer' script to check if it works - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot.Clone(), tx)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot.CreateSnapshot(), tx)) { if (engine.State == VMState.FAULT) { @@ -361,7 +361,7 @@ private Transaction MakeTransaction(StoreView snapshot, byte[] script, Signer[] throw new InvalidOperationException("Insufficient GAS"); } - public long CalculateNetworkFee(StoreView snapshot, Transaction tx) + public long CalculateNetworkFee(DataCache snapshot, Transaction tx) { UInt160[] hashes = tx.GetScriptHashesForVerifying(snapshot); @@ -401,7 +401,7 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) size += Array.Empty().GetVarSize() * 2; // Check verify cost - using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); + using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot()); engine.LoadContract(contract, md, CallFlags.None); if (NativeContract.IsNative(hash)) engine.Push("verify"); if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); diff --git a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs index 2e2b64ba64..9faadd2ee4 100644 --- a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -10,7 +10,7 @@ namespace Neo.UnitTests.Extensions { public static class NativeContractExtensions { - public static ContractState DeployContract(this StoreView snapshot, UInt160 sender, byte[] nefFile, byte[] manifest, long gas = 200_00000000) + public static ContractState DeployContract(this DataCache snapshot, UInt160 sender, byte[] nefFile, byte[] manifest, long gas = 200_00000000) { var script = new ScriptBuilder(); script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nefFile, manifest, null); @@ -31,7 +31,7 @@ public static ContractState DeployContract(this StoreView snapshot, UInt160 send return ret; } - public static void UpdateContract(this StoreView snapshot, UInt160 callingScriptHash, byte[] nefFile, byte[] manifest) + public static void UpdateContract(this DataCache snapshot, UInt160 callingScriptHash, byte[] nefFile, byte[] manifest) { var script = new ScriptBuilder(); script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "update", nefFile, manifest, null); @@ -54,7 +54,7 @@ public static void UpdateContract(this StoreView snapshot, UInt160 callingScript } } - public static void DestroyContract(this StoreView snapshot, UInt160 callingScriptHash) + public static void DestroyContract(this DataCache snapshot, UInt160 callingScriptHash) { var script = new ScriptBuilder(); script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "destroy"); @@ -77,24 +77,24 @@ public static void DestroyContract(this StoreView snapshot, UInt160 callingScrip } } - public static void AddContract(this StoreView snapshot, UInt160 hash, ContractState state) + public static void AddContract(this DataCache snapshot, UInt160 hash, ContractState state) { var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); - snapshot.Storages.Add(key, new Neo.Ledger.StorageItem(state, false)); + snapshot.Add(key, new StorageItem(state, false)); } - public static void DeleteContract(this StoreView snapshot, UInt160 hash) + public static void DeleteContract(this DataCache snapshot, UInt160 hash) { var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); - snapshot.Storages.Delete(key); + snapshot.Delete(key); } - public static StackItem Call(this NativeContract contract, StoreView snapshot, string method, params ContractParameter[] args) + public static StackItem Call(this NativeContract contract, DataCache snapshot, string method, params ContractParameter[] args) { return Call(contract, snapshot, null, null, method, args); } - public static StackItem Call(this NativeContract contract, StoreView snapshot, IVerifiable container, Block persistingBlock, string method, params ContractParameter[] args) + public static StackItem Call(this NativeContract contract, DataCache snapshot, IVerifiable container, Block persistingBlock, string method, params ContractParameter[] args) { var engine = ApplicationEngine.Create(TriggerType.Application, container, snapshot, persistingBlock); var contractState = NativeContract.ContractManagement.GetContract(snapshot, contract.Hash); diff --git a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs index 6f5d548a04..4cba1e19e2 100644 --- a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs @@ -28,14 +28,14 @@ public void Deserialize(BinaryReader reader) { } public void DeserializeUnsigned(BinaryReader reader) { } - public UInt160[] GetScriptHashesForVerifying(StoreView snapshot) => _hashForVerify; + public UInt160[] GetScriptHashesForVerifying(DataCache snapshot) => _hashForVerify; public void Serialize(BinaryWriter writer) { } public void SerializeUnsigned(BinaryWriter writer) { } } - public static bool Transfer(this NativeContract contract, StoreView snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom, Block persistingBlock) + public static bool Transfer(this NativeContract contract, DataCache snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom, Block persistingBlock) { var engine = ApplicationEngine.Create(TriggerType.Application, new ManualWitness(signFrom ? new UInt160(from) : null), snapshot, persistingBlock); @@ -61,7 +61,7 @@ public static bool Transfer(this NativeContract contract, StoreView snapshot, by return result.GetBoolean(); } - public static BigInteger TotalSupply(this NativeContract contract, StoreView snapshot) + public static BigInteger TotalSupply(this NativeContract contract, DataCache snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); @@ -79,7 +79,7 @@ public static BigInteger TotalSupply(this NativeContract contract, StoreView sna return result.GetInteger(); } - public static BigInteger BalanceOf(this NativeContract contract, StoreView snapshot, byte[] account) + public static BigInteger BalanceOf(this NativeContract contract, DataCache snapshot, byte[] account) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); @@ -98,7 +98,7 @@ public static BigInteger BalanceOf(this NativeContract contract, StoreView snaps return result.GetInteger(); } - public static BigInteger Decimals(this NativeContract contract, StoreView snapshot) + public static BigInteger Decimals(this NativeContract contract, DataCache snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); @@ -116,7 +116,7 @@ public static BigInteger Decimals(this NativeContract contract, StoreView snapsh return result.GetInteger(); } - public static string Symbol(this NativeContract contract, StoreView snapshot) + public static string Symbol(this NativeContract contract, DataCache snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); diff --git a/tests/neo.UnitTests/IO/Caching/UT_CloneCache.cs b/tests/neo.UnitTests/IO/Caching/UT_CloneCache.cs index b75a70ee97..097ec526db 100644 --- a/tests/neo.UnitTests/IO/Caching/UT_CloneCache.cs +++ b/tests/neo.UnitTests/IO/Caching/UT_CloneCache.cs @@ -1,39 +1,40 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; -using Neo.IO.Caching; +using Neo.Persistence; using System; using System.Collections.Generic; using System.Linq; +using System.Text; namespace Neo.UnitTests.IO.Caching { [TestClass] public class UT_CloneCache { - CloneCache cloneCache; - MyDataCache myDataCache; + ClonedCache clonedCache; + MyDataCache myDataCache; [TestInitialize] public void Init() { - myDataCache = new MyDataCache(); - cloneCache = new CloneCache(myDataCache); + myDataCache = new MyDataCache(); + clonedCache = new ClonedCache(myDataCache); } [TestMethod] public void TestCloneCache() { - cloneCache.Should().NotBeNull(); + clonedCache.Should().NotBeNull(); } [TestMethod] public void TestAddInternal() { - cloneCache.Add(new MyKey("key1"), new MyValue("value1")); - cloneCache[new MyKey("key1")].Should().Be(new MyValue("value1")); + clonedCache.Add(new MyKey("key1"), new MyValue("value1")); + clonedCache[new MyKey("key1")].Should().Be(new MyValue("value1")); - cloneCache.Commit(); + clonedCache.Commit(); myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1")); } @@ -41,53 +42,53 @@ public void TestAddInternal() public void TestDeleteInternal() { myDataCache.Add(new MyKey("key1"), new MyValue("value1")); - cloneCache.Delete(new MyKey("key1")); // trackable.State = TrackState.Deleted - cloneCache.Commit(); + clonedCache.Delete(new MyKey("key1")); // trackable.State = TrackState.Deleted + clonedCache.Commit(); - cloneCache.TryGet(new MyKey("key1")).Should().BeNull(); + clonedCache.TryGet(new MyKey("key1")).Should().BeNull(); myDataCache.TryGet(new MyKey("key1")).Should().BeNull(); } [TestMethod] public void TestFindInternal() { - cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + clonedCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.Add(new MyKey("key2"), new MyValue("value2")); myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); - var items = cloneCache.Find(new MyKey("key1").ToArray()); + var items = clonedCache.Find(new MyKey("key1").ToArray()); items.ElementAt(0).Key.Should().Be(new MyKey("key1")); items.ElementAt(0).Value.Should().Be(new MyValue("value1")); items.Count().Should().Be(1); - items = cloneCache.Find(new MyKey("key2").ToArray()); + items = clonedCache.Find(new MyKey("key2").ToArray()); items.ElementAt(0).Key.Should().Be(new MyKey("key2")); - items.ElementAt(0).Value.Should().Be(new MyValue("value2")); + new MyValue("value2").Should().Be(items.ElementAt(0).Value); items.Count().Should().Be(1); - items = cloneCache.Find(new MyKey("key3").ToArray()); + items = clonedCache.Find(new MyKey("key3").ToArray()); items.ElementAt(0).Key.Should().Be(new MyKey("key3")); - items.ElementAt(0).Value.Should().Be(new MyValue("value3")); + new MyValue("value3").Should().Be(items.ElementAt(0).Value); items.Count().Should().Be(1); - items = cloneCache.Find(new MyKey("key4").ToArray()); + items = clonedCache.Find(new MyKey("key4").ToArray()); items.Count().Should().Be(0); } [TestMethod] public void TestGetInternal() { - cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + clonedCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.Add(new MyKey("key2"), new MyValue("value2")); myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); - cloneCache[new MyKey("key1")].Should().Be(new MyValue("value1")); - cloneCache[new MyKey("key2")].Should().Be(new MyValue("value2")); - cloneCache[new MyKey("key3")].Should().Be(new MyValue("value3")); + new MyValue("value1").Should().Be(clonedCache[new MyKey("key1")]); + new MyValue("value2").Should().Be(clonedCache[new MyKey("key2")]); + new MyValue("value3").Should().Be(clonedCache[new MyKey("key3")]); Action action = () => { - var item = cloneCache[new MyKey("key4")]; + var item = clonedCache[new MyKey("key4")]; }; action.Should().Throw(); } @@ -95,33 +96,33 @@ public void TestGetInternal() [TestMethod] public void TestTryGetInternal() { - cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + clonedCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.Add(new MyKey("key2"), new MyValue("value2")); myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); - cloneCache.TryGet(new MyKey("key1")).Should().Be(new MyValue("value1")); - cloneCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2")); - cloneCache.TryGet(new MyKey("key3")).Should().Be(new MyValue("value3")); - cloneCache.TryGet(new MyKey("key4")).Should().BeNull(); + new MyValue("value1").Should().Be(clonedCache.TryGet(new MyKey("key1"))); + new MyValue("value2").Should().Be(clonedCache.TryGet(new MyKey("key2"))); + new MyValue("value3").Should().Be(clonedCache.TryGet(new MyKey("key3"))); + clonedCache.TryGet(new MyKey("key4")).Should().BeNull(); } [TestMethod] public void TestUpdateInternal() { - cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + clonedCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.Add(new MyKey("key2"), new MyValue("value2")); myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); - cloneCache.GetAndChange(new MyKey("key1")).Value = "value_new_1"; - cloneCache.GetAndChange(new MyKey("key2")).Value = "value_new_2"; - cloneCache.GetAndChange(new MyKey("key3")).Value = "value_new_3"; + clonedCache.GetAndChange(new MyKey("key1")).Value = Encoding.Default.GetBytes("value_new_1"); + clonedCache.GetAndChange(new MyKey("key2")).Value = Encoding.Default.GetBytes("value_new_2"); + clonedCache.GetAndChange(new MyKey("key3")).Value = Encoding.Default.GetBytes("value_new_3"); - cloneCache.Commit(); + clonedCache.Commit(); - cloneCache[new MyKey("key1")].Should().Be(new MyValue("value_new_1")); - cloneCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2")); - cloneCache[new MyKey("key3")].Should().Be(new MyValue("value_new_3")); - myDataCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2")); + new MyValue("value_new_1").Should().Be(clonedCache[new MyKey("key1")]); + new MyValue("value_new_2").Should().Be(clonedCache[new MyKey("key2")]); + new MyValue("value_new_3").Should().Be(clonedCache[new MyKey("key3")]); + new MyValue("value_new_2").Should().Be(clonedCache[new MyKey("key2")]); } } } diff --git a/tests/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs b/tests/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs deleted file mode 100644 index 591ea8ea05..0000000000 --- a/tests/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs +++ /dev/null @@ -1,48 +0,0 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO.Caching; - -namespace Neo.UnitTests.IO.Caching -{ - [TestClass] - public class UT_CloneMetaCache - { - MyMetaCache myMetaCache; - CloneMetaCache cloneMetaCache; - - [TestInitialize] - public void Init() - { - myMetaCache = new MyMetaCache(() => new MyValue()); - cloneMetaCache = new CloneMetaCache(myMetaCache); - } - - [TestMethod] - public void TestConstructor() - { - cloneMetaCache.Should().NotBeNull(); - } - - [TestMethod] - public void TestTryGetInternal() - { - MyValue value = myMetaCache.GetAndChange(); - value.Value = "value1"; - - cloneMetaCache.Get().Should().Be(value); - } - - [TestMethod] - public void TestUpdateInternal() - { - MyValue value = myMetaCache.GetAndChange(); - value.Value = "value1"; - - MyValue value2 = cloneMetaCache.GetAndChange(); - value2.Value = "value2"; - - cloneMetaCache.Commit(); - value.Value.Should().Be("value2"); - } - } -} diff --git a/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs b/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs index b085ac2e82..7b36f5e38a 100644 --- a/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs +++ b/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs @@ -1,171 +1,192 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; -using Neo.IO.Caching; +using Neo.Persistence; +using Neo.SmartContract; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; namespace Neo.UnitTests.IO.Caching { - class MyKey : ISerializable, IEquatable, IComparable + class MyKey : StorageKey, IEquatable, IComparable, IComparable, IEquatable, IComparable { - public string Key; - public int Size => Key.Length; - public MyKey() { } + public MyKey(UInt256 hash) + { + Key = hash.ToArray(); + } + + public MyKey(StorageKey key) + { + Id = key.Id; + Key = key.Key; + } public MyKey(string val) { - Key = val; + Key = Encoding.UTF8.GetBytes(val); } public void Deserialize(BinaryReader reader) { - Key = reader.ReadString(); + Key = Encoding.UTF8.GetBytes(reader.ReadString()); } public void Serialize(BinaryWriter writer) { writer.Write(Key); } - public bool Equals(MyKey other) { - return Key.Equals(other.Key); + if (other == null) return false; + return Id == other.Id && Key.SequenceEqual(other.Key); } public override bool Equals(object obj) { - if (!(obj is MyKey key)) return false; - return Equals(key); + if (obj is not MyKey other) return false; + return Id == other.Id && Key.SequenceEqual(other.Key); } public override int GetHashCode() { - return Key.GetHashCode(); + return HashCode.Combine(Id, Key.Length); } public int CompareTo(MyKey obj) { - return Key.CompareTo(obj.Key); + return CompareTo((StorageKey)obj); } - } - - public class MyValue : ISerializable, ICloneable - { - public string Value; - public int Size => Value.Length; - - public MyValue() { } + public int CompareTo(StorageKey obj) + { + if (obj is null) throw new Exception(); + int ret = Id.CompareTo(obj.Id); + if (ret != 0) return ret; + return Encoding.UTF8.GetString(Key).CompareTo(Encoding.UTF8.GetString(obj.Key)); + } - public MyValue(string val) + public int CompareTo(object obj) { - Value = val; + if (obj is not StorageKey key) throw new Exception(); + return CompareTo(key); } + } - public void Deserialize(BinaryReader reader) + public class MyValue : StorageItem, ISerializable, IEquatable, IEquatable + { + public MyValue(UInt256 hash) { - Value = reader.ReadString(); + Value = hash.ToArray(); } - public void Serialize(BinaryWriter writer) + public MyValue(string val) { - writer.Write(Value); + Value = Encoding.Default.GetBytes(val); } - MyValue ICloneable.Clone() + public MyValue(byte[] val) { - return new MyValue(Value); + Value = val; } - void ICloneable.FromReplica(MyValue replica) + public void FromReplica(MyValue replica) { Value = replica.Value; } + public bool Equals(StorageItem other) + { + if (other == null) return false; + return (Value == null && other.Value == null) || Value.SequenceEqual(other.Value); + } + public bool Equals(MyValue other) { - return (Value == null && other.Value == null) || Value.Equals(other.Value); + if (other == null) return false; + return (Value == null && other.Value == null) || Value.SequenceEqual(other.Value); } public override bool Equals(object obj) { - if (!(obj is MyValue key)) return false; - return Equals(key); + if (obj is not StorageItem other) return false; + return (Value == null && other.Value == null) || Value.SequenceEqual(other.Value); } public override int GetHashCode() { - return Value.GetHashCode(); + return Value.Length; } } - class MyDataCache : DataCache - where TKey : IEquatable, ISerializable, new() - where TValue : class, ICloneable, ISerializable, new() + class MyDataCache : DataCache { - public Dictionary InnerDict = new Dictionary(); + public Dictionary InnerDict = new Dictionary(); - protected override void DeleteInternal(TKey key) + protected override void DeleteInternal(StorageKey key) { InnerDict.Remove(key); } - protected override void AddInternal(TKey key, TValue value) + protected override void AddInternal(StorageKey key, StorageItem value) { - InnerDict.Add(key, value); + InnerDict.Add(key, new MyValue(value.Value)); } - protected override IEnumerable<(TKey, TValue)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) + protected override IEnumerable<(StorageKey, StorageItem)> SeekInternal(byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward) { if (direction == SeekDirection.Forward) - return InnerDict.OrderBy(kvp => kvp.Key).Where(kvp => ByteArrayComparer.Default.Compare(kvp.Key.ToArray(), keyOrPrefix) >= 0).Select(p => (p.Key, p.Value)); + return InnerDict.OrderBy(kvp => kvp.Key) + .Where(kvp => ByteArrayComparer.Default.Compare(kvp.Key.ToArray(), keyOrPrefix) >= 0) + .Select(p => (p.Key, (StorageItem)new MyValue(p.Value.Value))); else - return InnerDict.OrderByDescending(kvp => kvp.Key).Where(kvp => ByteArrayComparer.Reverse.Compare(kvp.Key.ToArray(), keyOrPrefix) >= 0).Select(p => (p.Key, p.Value)); + return InnerDict.OrderByDescending(kvp => kvp.Key) + .Where(kvp => ByteArrayComparer.Reverse.Compare(kvp.Key.ToArray(), keyOrPrefix) >= 0) + .Select(p => (p.Key, (StorageItem)new MyValue(p.Value.Value))); } - protected override TValue GetInternal(TKey key) + protected override StorageItem GetInternal(StorageKey key) { - if (InnerDict.TryGetValue(key, out TValue value)) + if (InnerDict.TryGetValue(key, out var value)) { - return value.Clone(); + return new MyValue(value.Value); } throw new KeyNotFoundException(); } - protected override TValue TryGetInternal(TKey key) + protected override StorageItem TryGetInternal(StorageKey key) { - if (InnerDict.TryGetValue(key, out TValue value)) + if (InnerDict.TryGetValue(key, out var value)) { - return value.Clone(); + return new MyValue(value.Value); } return null; } - protected override bool ContainsInternal(TKey key) + protected override bool ContainsInternal(StorageKey key) { return InnerDict.ContainsKey(key); } - protected override void UpdateInternal(TKey key, TValue value) + protected override void UpdateInternal(StorageKey key, StorageItem value) { - InnerDict[key] = value; + InnerDict[key] = new MyValue(value.Value); } } [TestClass] public class UT_DataCache { - MyDataCache myDataCache; + MyDataCache myDataCache; [TestInitialize] public void Initialize() { - myDataCache = new MyDataCache(); + myDataCache = new MyDataCache(); } [TestMethod] @@ -269,8 +290,8 @@ public void TestFind() myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4")); var items = myDataCache.Find(new MyKey("key1").ToArray()); - items.ElementAt(0).Key.Should().Be(new MyKey("key1")); - items.ElementAt(0).Value.Should().Be(new MyValue("value1")); + new MyKey("key1").Should().Be(items.ElementAt(0).Key); + new MyValue("value1").Should().Be(items.ElementAt(0).Value); items.Count().Should().Be(1); items = myDataCache.Find(new MyKey("key5").ToArray()); @@ -287,14 +308,14 @@ public void TestSeek() myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4")); var items = myDataCache.Seek(new MyKey("key3").ToArray(), SeekDirection.Backward).ToArray(); - items[0].Key.Should().Be(new MyKey("key3")); - items[0].Value.Should().Be(new MyValue("value3")); - items[1].Key.Should().Be(new MyKey("key2")); - items[1].Value.Should().Be(new MyValue("value2")); - items.Count().Should().Be(3); + new MyKey("key3").Should().Be(items[0].Key); + new MyValue("value3").Should().Be(items[0].Value); + new MyKey("key2").Should().Be(items[1].Key); + new MyValue("value2").Should().Be(items[1].Value); + items.Length.Should().Be(3); items = myDataCache.Seek(new MyKey("key5").ToArray(), SeekDirection.Forward).ToArray(); - items.Count().Should().Be(0); + items.Length.Should().Be(0); } [TestMethod] @@ -307,15 +328,15 @@ public void TestFindRange() myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4")); var items = myDataCache.FindRange(new MyKey("key3").ToArray(), new MyKey("key5").ToArray()).ToArray(); - items[0].Key.Should().Be(new MyKey("key3")); - items[0].Value.Should().Be(new MyValue("value3")); - items[1].Key.Should().Be(new MyKey("key4")); - items[1].Value.Should().Be(new MyValue("value4")); - items.Count().Should().Be(2); + new MyKey("key3").Should().Be(items[0].Key); + new MyValue("value3").Should().Be(items[0].Value); + new MyKey("key4").Should().Be(items[1].Key); + new MyValue("value4").Should().Be(items[1].Value); + items.Length.Should().Be(2); // case 2 Need to sort the cache of myDataCache - myDataCache = new MyDataCache(); + myDataCache = new MyDataCache(); myDataCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.Add(new MyKey("key2"), new MyValue("value2")); @@ -323,15 +344,15 @@ public void TestFindRange() myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); items = myDataCache.FindRange(new MyKey("key3").ToArray(), new MyKey("key5").ToArray()).ToArray(); - items[0].Key.Should().Be(new MyKey("key3")); - items[0].Value.Should().Be(new MyValue("value3")); - items[1].Key.Should().Be(new MyKey("key4")); - items[1].Value.Should().Be(new MyValue("value4")); - items.Count().Should().Be(2); + new MyKey("key3").Should().Be(items[0].Key); + new MyValue("value3").Should().Be(items[0].Value); + new MyKey("key4").Should().Be(items[1].Key); + new MyValue("value4").Should().Be(items[1].Value); + items.Length.Should().Be(2); // case 3 FindRange by Backward - myDataCache = new MyDataCache(); + myDataCache = new MyDataCache(); myDataCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.Add(new MyKey("key2"), new MyValue("value2")); @@ -340,11 +361,11 @@ public void TestFindRange() myDataCache.InnerDict.Add(new MyKey("key5"), new MyValue("value5")); items = myDataCache.FindRange(new MyKey("key5").ToArray(), new MyKey("key3").ToArray(), SeekDirection.Backward).ToArray(); - items[0].Key.Should().Be(new MyKey("key5")); - items[0].Value.Should().Be(new MyValue("value5")); - items[1].Key.Should().Be(new MyKey("key4")); - items[1].Value.Should().Be(new MyValue("value4")); - items.Count().Should().Be(2); + new MyKey("key5").Should().Be(items[0].Key); + new MyValue("value5").Should().Be(items[0].Value); + new MyKey("key4").Should().Be(items[1].Key); + new MyValue("value4").Should().Be(items[1].Value); + items.Length.Should().Be(2); } [TestMethod] @@ -363,8 +384,8 @@ public void TestGetChangeSet() foreach (var item in items) { i++; - item.Key.Should().Be(new MyKey("key" + i)); - item.Item.Should().Be(new MyValue("value" + i)); + new MyKey("key" + i).Should().Be(item.Key); + new MyValue("value" + i).Should().Be(item.Item); } i.Should().Be(4); } @@ -413,7 +434,7 @@ public void TestTryGet() [TestMethod] public void TestFindInvalid() { - var myDataCache = new MyDataCache(); + var myDataCache = new MyDataCache(); myDataCache.Add(new MyKey("key1"), new MyValue("value1")); myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); diff --git a/tests/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs b/tests/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs deleted file mode 100644 index 1ed84a5a0e..0000000000 --- a/tests/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs +++ /dev/null @@ -1,76 +0,0 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; -using Neo.IO.Caching; -using System; - -namespace Neo.UnitTests.IO.Caching -{ - public class MyMetaCache : MetaDataCache - where T : class, ICloneable, ISerializable, new() - { - public T Value; - - public MyMetaCache(Func factory) : base(factory) { } - - protected override void AddInternal(T item) - { - Value = item; - } - - protected override T TryGetInternal() - { - return Value; - } - - protected override void UpdateInternal(T item) - { - Value = item; - } - } - - [TestClass] - public class UT_MetaDataCache - { - MyMetaCache myMetaCache; - - [TestInitialize] - public void SetUp() - { - myMetaCache = new MyMetaCache(() => new MyValue()); - } - - [TestMethod] - public void TestContructor() - { - myMetaCache.Should().NotBeNull(); - } - - [TestMethod] - public void TestCommitAndAddInternal() - { - MyValue value = myMetaCache.Get(); - value.Should().NotBeNull(); - value.Value.Should().BeNull(); - - myMetaCache.Commit(); - myMetaCache.Value.Should().Be(value); - } - - public void TestCommitAndUpdateInternal() - { - MyValue value = myMetaCache.GetAndChange(); - value.Value = "value1"; - - myMetaCache.Commit(); - myMetaCache.Value.Should().Be(value); - myMetaCache.Value.Value.Should().Be("value1"); - } - - [TestMethod] - public void TestCreateSnapshot() - { - myMetaCache.CreateSnapshot().Should().NotBeNull(); - } - } -} diff --git a/tests/neo.UnitTests/IO/UT_SerializableWrapper.cs b/tests/neo.UnitTests/IO/UT_SerializableWrapper.cs deleted file mode 100644 index 0f73c40c38..0000000000 --- a/tests/neo.UnitTests/IO/UT_SerializableWrapper.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; -using System.IO; - -namespace Neo.UnitTests -{ - [TestClass] - public class UT_SerializableWrapper - { - [TestMethod] - public void TestGetSize() - { - SerializableWrapper temp = new SerializableWrapper(); - Assert.AreEqual(4, temp.Size); - } - - [TestMethod] - public void TestCast() - { - SerializableWrapper tempA = (SerializableWrapper)123; - SerializableWrapper tempB = tempA.ToArray().AsSerializable>(); - - Assert.IsTrue(tempA.Equals(tempB)); - Assert.AreEqual((uint)123, (uint)tempA); - } - - [TestMethod] - public void TestEqualsOtherObject() - { - MemoryStream stream = new MemoryStream(); - BinaryWriter writer = new BinaryWriter(stream); - BinaryReader reader = new BinaryReader(stream); - writer.Write((uint)1); - stream.Seek(0, SeekOrigin.Begin); - SerializableWrapper temp = new SerializableWrapper(); - temp.Deserialize(reader); - Assert.AreEqual(true, temp.Equals(1u)); - } - - [TestMethod] - public void TestEqualsOtherSerializableWrapper() - { - MemoryStream stream = new MemoryStream(); - BinaryWriter writer = new BinaryWriter(stream); - BinaryReader reader = new BinaryReader(stream); - writer.Write((uint)1); - stream.Seek(0, SeekOrigin.Begin); - SerializableWrapper temp = new SerializableWrapper(); - temp.Deserialize(reader); - MemoryStream stream2 = new MemoryStream(); - BinaryWriter writer2 = new BinaryWriter(stream2); - BinaryReader reader2 = new BinaryReader(stream2); - writer2.Write((uint)1); - stream2.Seek(0, SeekOrigin.Begin); - SerializableWrapper temp2 = new SerializableWrapper(); - temp2.Deserialize(reader2); - Assert.AreEqual(true, temp.Equals(temp2)); - } - } -} diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs index b0c12dc72e..c2051f40d4 100644 --- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs +++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs @@ -7,7 +7,6 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; -using Neo.VM; using Neo.Wallets; using Neo.Wallets.NEP6; using System; @@ -18,7 +17,7 @@ namespace Neo.UnitTests.Ledger { internal class TestBlock : Block { - public override bool Verify(StoreView snapshot) + public override bool Verify(DataCache snapshot) { return true; } @@ -31,7 +30,7 @@ public static TestBlock Cast(Block input) internal class TestHeader : Header { - public override bool Verify(StoreView snapshot) + public override bool Verify(DataCache snapshot) { return true; } @@ -62,51 +61,12 @@ public void Initialize() Blockchain.Singleton.MemPool.TryAdd(txSample, Blockchain.Singleton.GetSnapshot()); } - [TestMethod] - public void TestContainsBlock() - { - Blockchain.Singleton.ContainsBlock(UInt256.Zero).Should().BeFalse(); - } - - [TestMethod] - public void TestContainsTransaction() - { - Blockchain.Singleton.ContainsTransaction(UInt256.Zero).Should().BeFalse(); - Blockchain.Singleton.ContainsTransaction(txSample.Hash).Should().BeFalse(); - } - [TestMethod] public void TestGetCurrentBlockHash() { Blockchain.Singleton.CurrentBlockHash.Should().Be(UInt256.Parse("0x00c6803707b564153d444bfcdf3a13325fc96dda55cc8a740bbd543a1d752fda")); } - [TestMethod] - public void TestGetCurrentHeaderHash() - { - Blockchain.Singleton.CurrentHeaderHash.Should().Be(UInt256.Parse("0x00c6803707b564153d444bfcdf3a13325fc96dda55cc8a740bbd543a1d752fda")); - } - - [TestMethod] - public void TestGetBlock() - { - Blockchain.Singleton.GetBlock(UInt256.Zero).Should().BeNull(); - } - - [TestMethod] - public void TestGetBlockHash() - { - Blockchain.Singleton.GetBlockHash(0).Should().Be(UInt256.Parse("0x00c6803707b564153d444bfcdf3a13325fc96dda55cc8a740bbd543a1d752fda")); - Blockchain.Singleton.GetBlockHash(10).Should().BeNull(); - } - - [TestMethod] - public void TestGetTransaction() - { - Blockchain.Singleton.GetTransaction(UInt256.Zero).Should().BeNull(); - Blockchain.Singleton.GetTransaction(txSample.Hash).Should().BeNull(); - } - [TestMethod] public void TestValidTransaction() { @@ -120,7 +80,7 @@ public void TestValidTransaction() // Fake balance var key = new KeyBuilder(NativeContract.GAS.Id, 20).Add(acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 100_000_000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -139,34 +99,6 @@ public void TestValidTransaction() senderProbe.ExpectMsg(p => p.Result == VerifyResult.AlreadyExists); } - [TestMethod] - public void TestInvalidTransactionInPersist() - { - var snapshot = Blockchain.Singleton.GetSnapshot(); - var tx = new Transaction() - { - Attributes = Array.Empty(), - Signers = Array.Empty(), - NetworkFee = 0, - Nonce = (uint)Environment.TickCount, - Script = new byte[] { 1 }, - SystemFee = 0, - ValidUntilBlock = Blockchain.GenesisBlock.Index + 1, - Version = 0, - Witnesses = new Witness[0], - }; - StoreView clonedSnapshot = snapshot.Clone(); - var state = new TransactionState - { - BlockIndex = 0, - Transaction = tx - }; - clonedSnapshot.Transactions.Add(tx.Hash, state); - clonedSnapshot.Transactions.Commit(); - state.VMState = VMState.FAULT; - snapshot.Transactions.TryGet(tx.Hash).VMState.Should().Be(VMState.FAULT); - } - internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) { StorageKey storageKey = new StorageKey diff --git a/tests/neo.UnitTests/Ledger/UT_HashIndexState.cs b/tests/neo.UnitTests/Ledger/UT_HashIndexState.cs index b7a0de93c8..b47b44e224 100644 --- a/tests/neo.UnitTests/Ledger/UT_HashIndexState.cs +++ b/tests/neo.UnitTests/Ledger/UT_HashIndexState.cs @@ -1,7 +1,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; -using Neo.Ledger; +using Neo.SmartContract; +using Neo.SmartContract.Native; using System.IO; namespace Neo.UnitTests.Ledger @@ -22,42 +22,20 @@ public void Initialize() } [TestMethod] - public void TestClone() + public void TestDeserialize() { - HashIndexState dest = ((ICloneable)origin).Clone(); - dest.Hash.Should().Be(origin.Hash); - dest.Index.Should().Be(origin.Index); - } + using MemoryStream ms = new MemoryStream(1024); + using BinaryReader reader = new BinaryReader(ms); + + var data = BinarySerializer.Serialize(((IInteroperable)origin).ToStackItem(null), 1024); + ms.Write(data); + ms.Seek(0, SeekOrigin.Begin); - [TestMethod] - public void TestFromReplica() - { HashIndexState dest = new HashIndexState(); - ((ICloneable)dest).FromReplica(origin); + ((IInteroperable)dest).FromStackItem(BinarySerializer.Deserialize(reader, 1024, 1024, null)); + dest.Hash.Should().Be(origin.Hash); dest.Index.Should().Be(origin.Index); } - - [TestMethod] - public void TestGetSize() - { - ((ISerializable)origin).Size.Should().Be(36); - } - - [TestMethod] - public void TestDeserialize() - { - using (MemoryStream ms = new MemoryStream(1024)) - using (BinaryWriter writer = new BinaryWriter(ms)) - using (BinaryReader reader = new BinaryReader(ms)) - { - ((ISerializable)origin).Serialize(writer); - ms.Seek(0, SeekOrigin.Begin); - HashIndexState dest = new HashIndexState(); - ((ISerializable)dest).Deserialize(reader); - dest.Hash.Should().Be(origin.Hash); - dest.Index.Should().Be(origin.Index); - } - } } } diff --git a/tests/neo.UnitTests/Ledger/UT_HeaderHashList.cs b/tests/neo.UnitTests/Ledger/UT_HeaderHashList.cs deleted file mode 100644 index 482c620a00..0000000000 --- a/tests/neo.UnitTests/Ledger/UT_HeaderHashList.cs +++ /dev/null @@ -1,59 +0,0 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; -using Neo.Ledger; -using System.IO; - -namespace Neo.UnitTests.Ledger -{ - [TestClass] - public class UT_HeaderHashList - { - HeaderHashList origin; - - [TestInitialize] - public void Initialize() - { - origin = new HeaderHashList - { - Hashes = new UInt256[] { UInt256.Zero } - }; - } - - [TestMethod] - public void TestClone() - { - HeaderHashList dest = ((ICloneable)origin).Clone(); - dest.Hashes.Should().BeEquivalentTo(origin.Hashes); - } - - [TestMethod] - public void TestFromReplica() - { - HeaderHashList dest = new HeaderHashList(); - ((ICloneable)dest).FromReplica(origin); - dest.Hashes.Should().BeEquivalentTo(origin.Hashes); - } - - [TestMethod] - public void TestDeserialize() - { - using (MemoryStream ms = new MemoryStream(1024)) - using (BinaryWriter writer = new BinaryWriter(ms)) - using (BinaryReader reader = new BinaryReader(ms)) - { - ((ISerializable)origin).Serialize(writer); - ms.Seek(0, SeekOrigin.Begin); - HeaderHashList dest = new HeaderHashList(); - ((ISerializable)dest).Deserialize(reader); - dest.Hashes.Should().BeEquivalentTo(origin.Hashes); - } - } - - [TestMethod] - public void TestGetSize() - { - ((ISerializable)origin).Size.Should().Be(33); - } - } -} diff --git a/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs b/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs index 7edab47e07..8e8f31841c 100644 --- a/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -83,8 +83,8 @@ private Transaction CreateTransactionWithFee(long fee) var randomBytes = new byte[16]; random.NextBytes(randomBytes); Mock mock = new Mock(); - mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); - mock.Setup(p => p.VerifyStateDependent(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); + mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); + mock.Setup(p => p.VerifyStateDependent(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); mock.Setup(p => p.VerifyStateIndependent()).Returns(VerifyResult.Succeed); mock.Object.Script = randomBytes; mock.Object.NetworkFee = fee; @@ -108,8 +108,8 @@ private Transaction CreateTransactionWithFeeAndBalanceVerify(long fee) random.NextBytes(randomBytes); Mock mock = new Mock(); UInt160 sender = senderAccount; - mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); - mock.Setup(p => p.VerifyStateDependent(It.IsAny(), It.IsAny())).Returns((StoreView snapshot, TransactionVerificationContext context) => context.CheckTransaction(mock.Object, snapshot) ? VerifyResult.Succeed : VerifyResult.InsufficientFunds); + mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); + mock.Setup(p => p.VerifyStateDependent(It.IsAny(), It.IsAny())).Returns((DataCache snapshot, TransactionVerificationContext context) => context.CheckTransaction(mock.Object, snapshot) ? VerifyResult.Succeed : VerifyResult.InsufficientFunds); mock.Setup(p => p.VerifyStateIndependent()).Returns(VerifyResult.Succeed); mock.Object.Script = randomBytes; mock.Object.NetworkFee = fee; @@ -151,7 +151,7 @@ private void AddTransaction(Transaction txToAdd) _unit.TryAdd(txToAdd, snapshot); } - private void AddTransactionsWithBalanceVerify(int count, long fee, SnapshotView snapshot) + private void AddTransactionsWithBalanceVerify(int count, long fee, DataCache snapshot) { for (int i = 0; i < count; i++) { @@ -221,7 +221,7 @@ public void BlockPersistMovesTxToUnverifiedAndReverification() [TestMethod] public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() { - SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); + using SnapshotCache snapshot = Blockchain.Singleton.GetSnapshot(); BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, senderAccount); ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, long.MaxValue); NativeContract.GAS.Burn(engine, UInt160.Zero, balance); @@ -506,8 +506,8 @@ public void TestUpdatePoolForBlockPersisted() var key2 = CreateStorageKey(Prefix_FeePerByte); key1.Id = NativeContract.Policy.Id; key2.Id = NativeContract.Policy.Id; - snapshot.Storages.Add(key1, item1); - snapshot.Storages.Add(key2, item2); + snapshot.Add(key1, item1); + snapshot.Add(key2, item2); var tx1 = CreateTransaction(); var tx2 = CreateTransaction(); diff --git a/tests/neo.UnitTests/Ledger/UT_StorageItem.cs b/tests/neo.UnitTests/Ledger/UT_StorageItem.cs index 5ed24b5858..f9ced186ec 100644 --- a/tests/neo.UnitTests/Ledger/UT_StorageItem.cs +++ b/tests/neo.UnitTests/Ledger/UT_StorageItem.cs @@ -1,7 +1,6 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; -using Neo.Ledger; +using Neo.SmartContract; using System.IO; using System.Text; @@ -53,7 +52,7 @@ public void Clone() { uut.Value = TestUtils.GetByteArray(10, 0x42); - StorageItem newSi = ((ICloneable)uut).Clone(); + StorageItem newSi = uut.Clone(); newSi.Value.Length.Should().Be(10); newSi.Value[0].Should().Be(0x42); for (int i = 1; i < 10; i++) @@ -112,7 +111,7 @@ public void TestFromReplica() uut.Value = TestUtils.GetByteArray(10, 0x42); uut.IsConstant = true; StorageItem dest = new StorageItem(); - ((ICloneable)dest).FromReplica(uut); + dest.FromReplica(uut); dest.Value.Should().BeEquivalentTo(uut.Value); dest.IsConstant.Should().Be(uut.IsConstant); } diff --git a/tests/neo.UnitTests/Ledger/UT_StorageKey.cs b/tests/neo.UnitTests/Ledger/UT_StorageKey.cs index e71cdba716..1aa347eb5e 100644 --- a/tests/neo.UnitTests/Ledger/UT_StorageKey.cs +++ b/tests/neo.UnitTests/Ledger/UT_StorageKey.cs @@ -1,7 +1,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; -using Neo.Ledger; +using Neo.SmartContract; using System.IO; namespace Neo.UnitTests.Ledger diff --git a/tests/neo.UnitTests/Ledger/UT_TransactionState.cs b/tests/neo.UnitTests/Ledger/UT_TransactionState.cs index cfb3f84d2d..6d06e582a1 100644 --- a/tests/neo.UnitTests/Ledger/UT_TransactionState.cs +++ b/tests/neo.UnitTests/Ledger/UT_TransactionState.cs @@ -1,8 +1,8 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; -using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; using System; using System.IO; @@ -19,8 +19,7 @@ public void Initialize() origin = new TransactionState { BlockIndex = 1, - VMState = VM.VMState.NONE, - Transaction = new Neo.Network.P2P.Payloads.Transaction() + Transaction = new Transaction() { Attributes = Array.Empty(), Script = new byte[] { 0x01 }, @@ -34,45 +33,20 @@ public void Initialize() } [TestMethod] - public void TestClone() + public void TestDeserialize() { - TransactionState dest = ((ICloneable)origin).Clone(); - dest.BlockIndex.Should().Be(origin.BlockIndex); - dest.VMState.Should().Be(origin.VMState); - dest.Transaction.Should().Be(origin.Transaction); - } + using MemoryStream ms = new MemoryStream(1024); + using BinaryReader reader = new BinaryReader(ms); - [TestMethod] - public void TestFromReplica() - { - TransactionState dest = new TransactionState(); - ((ICloneable)dest).FromReplica(origin); - dest.BlockIndex.Should().Be(origin.BlockIndex); - dest.VMState.Should().Be(origin.VMState); - dest.Transaction.Should().Be(origin.Transaction); - } + var data = BinarySerializer.Serialize(((IInteroperable)origin).ToStackItem(null), 1024); + ms.Write(data); + ms.Seek(0, SeekOrigin.Begin); - [TestMethod] - public void TestDeserialize() - { - using (MemoryStream ms = new MemoryStream(1024)) - using (BinaryWriter writer = new BinaryWriter(ms)) - using (BinaryReader reader = new BinaryReader(ms)) - { - ((ISerializable)origin).Serialize(writer); - ms.Seek(0, SeekOrigin.Begin); - TransactionState dest = new TransactionState(); - ((ISerializable)dest).Deserialize(reader); - dest.BlockIndex.Should().Be(origin.BlockIndex); - dest.VMState.Should().Be(origin.VMState); - dest.Transaction.Hash.Should().Be(origin.Transaction.Hash); - } - } + TransactionState dest = new TransactionState(); + ((IInteroperable)dest).FromStackItem(BinarySerializer.Deserialize(reader, 1024, 1024, null)); - [TestMethod] - public void TestGetSize() - { - ((ISerializable)origin).Size.Should().Be(58); + dest.BlockIndex.Should().Be(origin.BlockIndex); + dest.Transaction.Hash.Should().Be(origin.Transaction.Hash); } } } diff --git a/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs b/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs index 2de4f9084a..291d9b7d1a 100644 --- a/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs +++ b/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs @@ -28,8 +28,8 @@ private Transaction CreateTransactionWithFee(long networkFee, long systemFee) var randomBytes = new byte[16]; random.NextBytes(randomBytes); Mock mock = new Mock(); - mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); - mock.Setup(p => p.VerifyStateDependent(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); + mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); + mock.Setup(p => p.VerifyStateDependent(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed); mock.Setup(p => p.VerifyStateIndependent()).Returns(VerifyResult.Succeed); mock.Object.Script = randomBytes; mock.Object.NetworkFee = networkFee; diff --git a/tests/neo.UnitTests/Ledger/UT_TrimmedBlock.cs b/tests/neo.UnitTests/Ledger/UT_TrimmedBlock.cs index c8b0e30fb8..c27413f1d3 100644 --- a/tests/neo.UnitTests/Ledger/UT_TrimmedBlock.cs +++ b/tests/neo.UnitTests/Ledger/UT_TrimmedBlock.cs @@ -1,8 +1,9 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.SmartContract.Native; +using Neo.UnitTests.SmartContract; using Neo.VM; using System; using System.IO; @@ -24,19 +25,17 @@ public static TrimmedBlock GetTrimmedBlockWithNoTransaction() NextConsensus = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), Witness = new Witness { - InvocationScript = new byte[0], + InvocationScript = Array.Empty(), VerificationScript = new[] { (byte)OpCode.PUSH1 } }, - Hashes = new UInt256[0] + Hashes = Array.Empty() }; } - [TestMethod] - public void TestGetIsBlock() + [TestInitialize] + public void Init() { - TrimmedBlock block = GetTrimmedBlockWithNoTransaction(); - block.Hashes = new UInt256[] { TestUtils.GetTransaction(UInt160.Zero).Hash }; - block.IsBlock.Should().BeTrue(); + TestBlockchain.InitializeMockNeoSystem(); } [TestMethod] @@ -63,17 +62,20 @@ public void TestGetBlock() Transaction = tx2, BlockIndex = 1 }; - snapshot.Transactions.Add(tx1.Hash, state1); - snapshot.Transactions.Add(tx2.Hash, state2); + UT_SmartContractHelper.TransactionAdd(snapshot, state1, state2); TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { tx1.Hash, tx2.Hash }; - Block block = tblock.GetBlock(snapshot.Transactions); + UT_SmartContractHelper.BlocksAdd(snapshot, tblock.Hash, tblock); + + Block block = NativeContract.Ledger.GetBlock(snapshot, tblock.Hash); block.Index.Should().Be(1); block.MerkleRoot.Should().Be(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff02")); block.Transactions.Length.Should().Be(1); block.Transactions[0].Hash.Should().Be(tx2.Hash); + block.Witness.InvocationScript.ToHexString().Should().Be(tblock.Witness.InvocationScript.ToHexString()); + block.Witness.VerificationScript.ToHexString().Should().Be(tblock.Witness.VerificationScript.ToHexString()); } [TestMethod] @@ -114,25 +116,5 @@ public void TestDeserialize() tblock.Witness.ScriptHash.Should().Be(newBlock.Witness.ScriptHash); tblock.ToJson().ToString().Should().Be(newBlock.ToJson().ToString()); } - - [TestMethod] - public void TestClone() - { - TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); - tblock.Hashes = new UInt256[] { TestUtils.GetTransaction(UInt160.Zero).Hash }; - ICloneable cloneable = tblock; - var clonedBlock = cloneable.Clone(); - clonedBlock.ToJson().ToString().Should().Be(tblock.ToJson().ToString()); - } - - [TestMethod] - public void TestFromReplica() - { - TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); - tblock.Hashes = new UInt256[] { TestUtils.GetTransaction(UInt160.Zero).Hash }; - ICloneable cloneable = new TrimmedBlock(); - cloneable.FromReplica(tblock); - ((TrimmedBlock)cloneable).ToJson().ToString().Should().Be(tblock.ToJson().ToString()); - } } } diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs index 0d5208de5a..533f277f9a 100644 --- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs +++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs @@ -135,13 +135,7 @@ public void Equals_DiffObj() Block newBlock = new Block(); UInt256 val256 = UInt256.Zero; UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42)); - UInt256 merkRoot; - UInt160 val160; - ulong timestampVal; - uint indexVal; - Witness scriptVal; - Transaction[] transactionsVal; - TestUtils.SetupBlockWithValues(newBlock, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); + TestUtils.SetupBlockWithValues(newBlock, val256, out UInt256 merkRoot, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, 1); TestUtils.SetupBlockWithValues(uut, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 0); uut.Equals(newBlock).Should().BeFalse(); @@ -156,16 +150,9 @@ public void Equals_Null() [TestMethod] public void Equals_SameHash() { - Block newBlock = new Block(); UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42)); - UInt256 merkRoot; - UInt160 val160; - ulong timestampVal; - uint indexVal; - Witness scriptVal; - Transaction[] transactionsVal; - TestUtils.SetupBlockWithValues(newBlock, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); + TestUtils.SetupBlockWithValues(newBlock, prevHash, out UInt256 merkRoot, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, 1); TestUtils.SetupBlockWithValues(uut, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); uut.Equals(newBlock).Should().BeTrue(); @@ -175,19 +162,11 @@ public void Equals_SameHash() public void RebuildMerkleRoot_Updates() { UInt256 val256 = UInt256.Zero; - UInt256 merkRoot; - UInt160 val160; - ulong timestampVal; - uint indexVal; - Witness scriptVal; - Transaction[] transactionsVal; - TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); - + TestUtils.SetupBlockWithValues(uut, val256, out UInt256 merkRoot, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, 1); UInt256 merkleRoot = uut.MerkleRoot; TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 3); uut.RebuildMerkleRoot(); - uut.MerkleRoot.Should().NotBe(merkleRoot); } diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs index afec8fd41c..fcc9c3e1ee 100644 --- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs +++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs @@ -1,7 +1,10 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; +using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.SmartContract.Native; +using Neo.UnitTests.SmartContract; using System.IO; namespace Neo.UnitTests.Network.P2P.Payloads @@ -14,6 +17,7 @@ public class UT_Header [TestInitialize] public void TestSetup() { + TestBlockchain.InitializeMockNeoSystem(); uut = new Header(); } @@ -39,8 +43,22 @@ public void GetHashCodeTest() public void TrimTest() { UInt256 val256 = UInt256.Zero; + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); TestUtils.SetupHeaderWithValues(uut, val256, out _, out _, out _, out _, out _); - var trim = uut.Trim(); + uut.Witness = new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] }; + + UT_SmartContractHelper.BlocksAdd(snapshot, uut.Hash, new TrimmedBlock() + { + Timestamp = uut.Timestamp, + PrevHash = uut.PrevHash, + MerkleRoot = uut.MerkleRoot, + ConsensusData = new ConsensusData(), + Hashes = new UInt256[0], + NextConsensus = uut.NextConsensus, + Witness = uut.Witness + }); + + var trim = NativeContract.Ledger.GetTrimmedBlock(snapshot, uut.Hash); trim.Version.Should().Be(uut.Version); trim.PrevHash.Should().Be(uut.PrevHash); @@ -48,7 +66,7 @@ public void TrimTest() trim.Timestamp.Should().Be(uut.Timestamp); trim.Index.Should().Be(uut.Index); trim.NextConsensus.Should().Be(uut.NextConsensus); - trim.Witness.Should().Be(uut.Witness); + trim.Witness.Should().BeEquivalentTo(uut.Witness); trim.Hashes.Length.Should().Be(0); } @@ -64,16 +82,14 @@ public void Deserialize() using (MemoryStream ms = new MemoryStream(hex.HexToBytes(), false)) { - using (BinaryReader reader = new BinaryReader(ms)) - { - uut.Deserialize(reader); - } + using BinaryReader reader = new BinaryReader(ms); + uut.Deserialize(reader); } - assertStandardHeaderTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal); + AssertStandardHeaderTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal); } - private void assertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, ulong timestampVal, uint indexVal, Witness scriptVal) + private void AssertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, ulong timestampVal, uint indexVal, Witness scriptVal) { uut.PrevHash.Should().Be(val256); uut.MerkleRoot.Should().Be(merkRoot); diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index b4f0934307..bd949063d3 100644 --- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -125,7 +125,7 @@ public void FeeIsMultiSigContract() // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -195,7 +195,7 @@ public void FeeIsSignatureContractDetailed() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -305,7 +305,7 @@ public void FeeIsSignatureContract_TestScope_Global() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -391,7 +391,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -478,7 +478,7 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -568,7 +568,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -618,7 +618,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -710,7 +710,7 @@ public void FeeIsSignatureContract_TestScope_NoScopeFAULT() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -971,7 +971,7 @@ public void FeeIsSignatureContract_TestScope_FeeOnly_Default() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -1114,7 +1114,7 @@ public void Test_VerifyStateIndependent() // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -1148,6 +1148,7 @@ public void Test_VerifyStateIndependent() public void Test_VerifyStateDependent() { var snapshot = Blockchain.Singleton.GetSnapshot(); + var height = NativeContract.Ledger.CurrentIndex(snapshot); var tx = new Transaction() { Attributes = Array.Empty(), @@ -1156,7 +1157,7 @@ public void Test_VerifyStateDependent() Script = new byte[0], Signers = new Signer[] { new Signer() { Account = UInt160.Zero } }, SystemFee = 0, - ValidUntilBlock = snapshot.Height + 1, + ValidUntilBlock = height + 1, Version = 0, Witnesses = new Witness[0], }; @@ -1186,7 +1187,7 @@ public void Test_VerifyStateDependent() // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; @@ -1256,7 +1257,7 @@ public void Test_Verify() // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; diff --git a/tests/neo.UnitTests/Persistence/UT_MemoryStore.cs b/tests/neo.UnitTests/Persistence/UT_MemoryStore.cs index 101ed0bdfc..5feff2b677 100644 --- a/tests/neo.UnitTests/Persistence/UT_MemoryStore.cs +++ b/tests/neo.UnitTests/Persistence/UT_MemoryStore.cs @@ -13,17 +13,17 @@ public void StoreTest() { using var store = new MemoryStore(); - store.Delete(0, new byte[] { 1 }); - Assert.AreEqual(null, store.TryGet(1, new byte[] { 1 })); - store.Put(1, new byte[] { 1 }, new byte[] { 1, 2, 3 }); - CollectionAssert.AreEqual(new byte[] { 1, 2, 3 }, store.TryGet(1, new byte[] { 1 })); + store.Delete(new byte[] { 1 }); + Assert.AreEqual(null, store.TryGet(new byte[] { 1 })); + store.Put(new byte[] { 1 }, new byte[] { 1, 2, 3 }); + CollectionAssert.AreEqual(new byte[] { 1, 2, 3 }, store.TryGet(new byte[] { 1 })); - store.Put(1, new byte[] { 2 }, new byte[] { 4, 5, 6 }); - CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(1, new byte[] { }, SeekDirection.Forward).Select(u => u.Key).First()); - CollectionAssert.AreEqual(new byte[] { 2 }, store.Seek(1, new byte[] { }, SeekDirection.Backward).Select(u => u.Key).First()); - CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(1, new byte[] { 1 }, SeekDirection.Backward).Select(u => u.Key).First()); + store.Put(new byte[] { 2 }, new byte[] { 4, 5, 6 }); + CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(new byte[] { }, SeekDirection.Forward).Select(u => u.Key).First()); + CollectionAssert.AreEqual(new byte[] { 2 }, store.Seek(new byte[] { }, SeekDirection.Backward).Select(u => u.Key).First()); + CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(new byte[] { 1 }, SeekDirection.Backward).Select(u => u.Key).First()); - store.Delete(0, new byte[] { 1 }); + store.Delete(new byte[] { 1 }); } } } diff --git a/tests/neo.UnitTests/Persistence/UT_ReadOnlyView.cs b/tests/neo.UnitTests/Persistence/UT_ReadOnlyView.cs deleted file mode 100644 index 4e7921cb00..0000000000 --- a/tests/neo.UnitTests/Persistence/UT_ReadOnlyView.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.Persistence; -using System; -using System.Linq; - -namespace Neo.UnitTests.Persistence -{ - [TestClass] - public class UT_ReadOnlyView - { - [TestMethod] - public void CommitException() - { - var r = new ReadOnlyView(new MemoryStore()); - Assert.ThrowsException(() => r.Commit()); - } - - [TestMethod] - public void Stores() - { - var r = new ReadOnlyView(new MemoryStore()); - - Assert.AreEqual(uint.MaxValue, r.BlockHashIndex.Get().Index); - Assert.AreEqual(UInt256.Zero, r.BlockHashIndex.Get().Hash); - Assert.AreEqual(uint.MaxValue, r.HeaderHashIndex.Get().Index); - Assert.AreEqual(UInt256.Zero, r.HeaderHashIndex.Get().Hash); - Assert.AreEqual(0, r.Blocks.Find().Count()); - Assert.AreEqual(0, r.Transactions.Find().Count()); - Assert.AreEqual(0, r.Storages.Find().Count()); - Assert.AreEqual(0, r.HeaderHashList.Find().Count()); - } - } -} diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_FungibleToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_FungibleToken.cs index 8018dcaa16..fdf93436f4 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_FungibleToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_FungibleToken.cs @@ -2,6 +2,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Ledger; +using Neo.SmartContract; using Neo.SmartContract.Native; using System; using System.Numerics; @@ -39,7 +40,7 @@ public void TestTotalSupply() key.Id = test.Id; - snapshot.Storages.Add(key, item); + snapshot.Add(key, item); test.TotalSupply(snapshot).Should().Be(1); } @@ -59,7 +60,7 @@ public void TestTotalSupplyDecimal() key.Id = test.Id; - snapshot.Storages.Add(key, item); + snapshot.Add(key, item); test.TotalSupply(snapshot).Should().Be(10_000_000_000_000_000); } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs index 7bcfe23bdd..ada89b0973 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs @@ -17,7 +17,7 @@ namespace Neo.UnitTests.SmartContract.Native [TestClass] public class UT_GasToken { - private StoreView _snapshot; + private DataCache _snapshot; private Block _persistingBlock; [TestInitialize] @@ -41,11 +41,11 @@ public void TestSetup() [TestMethod] public void Check_BalanceOfTransferAndBurn() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; - byte[] from = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); + byte[] from = Contract.GetBFTAddress(Blockchain.StandbyValidators).ToArray(); byte[] to = new byte[20]; - var keyCount = snapshot.Storages.GetChangeSet().Count(); + var keyCount = snapshot.GetChangeSet().Count(); var supply = NativeContract.GAS.TotalSupply(snapshot); supply.Should().Be(3000000050000000); // 3000000000000000 + 50000000 (neo holder reward) @@ -73,11 +73,11 @@ public void Check_BalanceOfTransferAndBurn() supply = NativeContract.GAS.TotalSupply(snapshot); supply.Should().Be(3000050050000000); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 3); // Gas + snapshot.GetChangeSet().Count().Should().Be(keyCount + 3); // Gas // Transfer - keyCount = snapshot.Storages.GetChangeSet().Count(); + keyCount = snapshot.GetChangeSet().Count(); NativeContract.GAS.Transfer(snapshot, from, to, 30000500_00000000, false, persistingBlock).Should().BeFalse(); // Not signed NativeContract.GAS.Transfer(snapshot, from, to, 30000500_00000001, true, persistingBlock).Should().BeFalse(); // More than balance @@ -88,12 +88,12 @@ public void Check_BalanceOfTransferAndBurn() NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(30000500_00000000); NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(0); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); // All + snapshot.GetChangeSet().Count().Should().Be(keyCount + 1); // All // Burn using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, persistingBlock, 0); - keyCount = snapshot.Storages.GetChangeSet().Count(); + keyCount = snapshot.GetChangeSet().Count(); Assert.ThrowsException(() => NativeContract.GAS.Burn(engine, new UInt160(to), BigInteger.MinusOne)); @@ -109,13 +109,13 @@ public void Check_BalanceOfTransferAndBurn() NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000049999999999); - keyCount.Should().Be(snapshot.Storages.GetChangeSet().Count()); + keyCount.Should().Be(snapshot.GetChangeSet().Count()); // Burn all NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000049999999999)); - (keyCount - 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); + (keyCount - 1).Should().Be(snapshot.GetChangeSet().Count()); // Bad inputs diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NameService.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NameService.cs index 507bd4e90c..8e87e36c4c 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NameService.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NameService.cs @@ -18,7 +18,7 @@ namespace Neo.UnitTests.SmartContract.Native [TestClass] public class UT_NameService : TestKit { - protected StoreView _snapshot; + protected DataCache _snapshot; [TestInitialize] public void TestSetup() @@ -37,7 +37,7 @@ public void TestInfo() [TestMethod] public void TestRoots() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; var from = NativeContract.NEO.GetCommitteeAddress(snapshot); @@ -62,7 +62,7 @@ public void TestRoots() [TestMethod] public void TestPrice() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; var from = NativeContract.NEO.GetCommitteeAddress(snapshot); @@ -87,7 +87,7 @@ public void TestPrice() [TestMethod] public void TestRegister() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000, Timestamp = 0 }; var from = NativeContract.NEO.GetCommitteeAddress(snapshot); @@ -126,7 +126,7 @@ public void TestRegister() [TestMethod] public void TestSetRecord() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000, Timestamp = 0 }; var from = NativeContract.NEO.GetCommitteeAddress(snapshot); @@ -158,7 +158,7 @@ public void TestSetRecord() CollectionAssert.AreEqual(System.Array.Empty(), NativeContract.NameService.GetRecords(snapshot, "neo.com").Select(u => u.Type.ToString() + "=" + u.Data).ToArray()); } - internal static bool Check_DeleteRecord(StoreView snapshot, string name, RecordType type, UInt160 signedBy, Block persistingBlock) + internal static bool Check_DeleteRecord(DataCache snapshot, string name, RecordType type, UInt160 signedBy, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signedBy), snapshot, persistingBlock); using var script = new ScriptBuilder(); @@ -176,7 +176,7 @@ internal static bool Check_DeleteRecord(StoreView snapshot, string name, RecordT return true; } - internal static bool Check_SetRecord(StoreView snapshot, string name, RecordType type, string data, UInt160 signedBy, Block persistingBlock) + internal static bool Check_SetRecord(DataCache snapshot, string name, RecordType type, string data, UInt160 signedBy, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signedBy), snapshot, persistingBlock); using var script = new ScriptBuilder(); @@ -195,7 +195,7 @@ internal static bool Check_SetRecord(StoreView snapshot, string name, RecordType return true; } - internal static BigInteger Check_Renew(StoreView snapshot, string name, UInt160 signedBy, Block persistingBlock) + internal static BigInteger Check_Renew(DataCache snapshot, string name, UInt160 signedBy, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signedBy), snapshot, persistingBlock); using var script = new ScriptBuilder(); @@ -215,7 +215,7 @@ internal static BigInteger Check_Renew(StoreView snapshot, string name, UInt160 return result.GetInteger(); } - internal static bool Check_SetAdmin(StoreView snapshot, string name, UInt160 admin, UInt160 signedBy, Block persistingBlock) + internal static bool Check_SetAdmin(DataCache snapshot, string name, UInt160 admin, UInt160 signedBy, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(admin, signedBy), snapshot, persistingBlock); using var script = new ScriptBuilder(); @@ -233,7 +233,7 @@ internal static bool Check_SetAdmin(StoreView snapshot, string name, UInt160 adm return true; } - internal static bool Check_Register(StoreView snapshot, string name, UInt160 owner, Block persistingBlock) + internal static bool Check_Register(DataCache snapshot, string name, UInt160 owner, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(owner), snapshot, persistingBlock); using var script = new ScriptBuilder(); @@ -254,7 +254,7 @@ internal static bool Check_Register(StoreView snapshot, string name, UInt160 own return result.GetBoolean(); } - internal static bool Check_SetPrice(StoreView snapshot, UInt160 signedBy, long price, Block persistingBlock) + internal static bool Check_SetPrice(DataCache snapshot, UInt160 signedBy, long price, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signedBy), snapshot, persistingBlock); using var script = new ScriptBuilder(); @@ -269,7 +269,7 @@ internal static bool Check_SetPrice(StoreView snapshot, UInt160 signedBy, long p return true; } - internal static bool Check_AddRoot(StoreView snapshot, UInt160 signedBy, string root, Block persistingBlock) + internal static bool Check_AddRoot(DataCache snapshot, UInt160 signedBy, string root, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signedBy), snapshot, persistingBlock); using var script = new ScriptBuilder(); diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index ccb340864f..dcd67d350b 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -3,7 +3,6 @@ using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; -using Neo.IO.Caching; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; @@ -22,7 +21,7 @@ namespace Neo.UnitTests.SmartContract.Native [TestClass] public class UT_NeoToken { - private StoreView _snapshot; + private DataCache _snapshot; private Block _persistingBlock; [TestInitialize] @@ -45,10 +44,10 @@ public void TestSetup() [TestMethod] public void Check_Vote() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; - byte[] from = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); + byte[] from = Contract.GetBFTAddress(Blockchain.StandbyValidators).ToArray(); // No signature @@ -80,7 +79,7 @@ public void Check_Vote() // no registered - var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, from)).GetInteroperable(); + var accountState = snapshot.TryGet(CreateStorageKey(20, from)).GetInteroperable(); accountState.VoteTo = null; ret = Check_Vote(snapshot, from, ECCurve.Secp256r1.G.ToArray(), true, persistingBlock); ret.Result.Should().BeFalse(); @@ -89,7 +88,7 @@ public void Check_Vote() // normal case - snapshot.Storages.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); + snapshot.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); ret = Check_Vote(snapshot, from, ECCurve.Secp256r1.G.ToArray(), true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); @@ -99,24 +98,24 @@ public void Check_Vote() [TestMethod] public void Check_Vote_Sameaccounts() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; - byte[] from = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); - var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, from)).GetInteroperable(); + byte[] from = Contract.GetBFTAddress(Blockchain.StandbyValidators).ToArray(); + var accountState = snapshot.TryGet(CreateStorageKey(20, from)).GetInteroperable(); accountState.Balance = 100; - snapshot.Storages.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); + snapshot.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); var ret = Check_Vote(snapshot, from, ECCurve.Secp256r1.G.ToArray(), true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); accountState.VoteTo.Should().Be(ECCurve.Secp256r1.G); //two account vote for the same account - var stateValidator = snapshot.Storages.GetAndChange(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray())).GetInteroperable(); + var stateValidator = snapshot.GetAndChange(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray())).GetInteroperable(); stateValidator.Votes.Should().Be(100); var G_Account = Contract.CreateSignatureContract(ECCurve.Secp256r1.G).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState { Balance = 200 })); - var secondAccount = snapshot.Storages.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable(); + snapshot.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState { Balance = 200 })); + var secondAccount = snapshot.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable(); ret = Check_Vote(snapshot, G_Account, ECCurve.Secp256r1.G.ToArray(), true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); @@ -126,57 +125,57 @@ public void Check_Vote_Sameaccounts() [TestMethod] public void Check_Vote_ChangeVote() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; //from vote to G byte[] from = Blockchain.StandbyValidators[0].ToArray(); var from_Account = Contract.CreateSignatureContract(Blockchain.StandbyValidators[0]).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, from_Account), new StorageItem(new NeoAccountState())); - var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, from_Account)).GetInteroperable(); + snapshot.Add(CreateStorageKey(20, from_Account), new StorageItem(new NeoAccountState())); + var accountState = snapshot.TryGet(CreateStorageKey(20, from_Account)).GetInteroperable(); accountState.Balance = 100; - snapshot.Storages.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); + snapshot.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); var ret = Check_Vote(snapshot, from_Account, ECCurve.Secp256r1.G.ToArray(), true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); accountState.VoteTo.Should().Be(ECCurve.Secp256r1.G); //from change vote to itself - var G_stateValidator = snapshot.Storages.GetAndChange(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray())).GetInteroperable(); + var G_stateValidator = snapshot.GetAndChange(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray())).GetInteroperable(); G_stateValidator.Votes.Should().Be(100); var G_Account = Contract.CreateSignatureContract(ECCurve.Secp256r1.G).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState { Balance = 200 })); - snapshot.Storages.Add(CreateStorageKey(33, from), new StorageItem(new CandidateState())); + snapshot.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState { Balance = 200 })); + snapshot.Add(CreateStorageKey(33, from), new StorageItem(new CandidateState())); ret = Check_Vote(snapshot, from_Account, from, true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); G_stateValidator.Votes.Should().Be(0); - var from_stateValidator = snapshot.Storages.GetAndChange(CreateStorageKey(33, from)).GetInteroperable(); + var from_stateValidator = snapshot.GetAndChange(CreateStorageKey(33, from)).GetInteroperable(); from_stateValidator.Votes.Should().Be(100); } [TestMethod] public void Check_Vote_VoteToNull() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; byte[] from = Blockchain.StandbyValidators[0].ToArray(); var from_Account = Contract.CreateSignatureContract(Blockchain.StandbyValidators[0]).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, from_Account), new StorageItem(new NeoAccountState())); - var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, from_Account)).GetInteroperable(); + snapshot.Add(CreateStorageKey(20, from_Account), new StorageItem(new NeoAccountState())); + var accountState = snapshot.TryGet(CreateStorageKey(20, from_Account)).GetInteroperable(); accountState.Balance = 100; - snapshot.Storages.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); + snapshot.Add(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()), new StorageItem(new CandidateState())); var ret = Check_Vote(snapshot, from_Account, ECCurve.Secp256r1.G.ToArray(), true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); accountState.VoteTo.Should().Be(ECCurve.Secp256r1.G); //from vote to null account G votes becomes 0 - var G_stateValidator = snapshot.Storages.GetAndChange(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray())).GetInteroperable(); + var G_stateValidator = snapshot.GetAndChange(CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray())).GetInteroperable(); G_stateValidator.Votes.Should().Be(100); var G_Account = Contract.CreateSignatureContract(ECCurve.Secp256r1.G).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState { Balance = 200 })); - snapshot.Storages.Add(CreateStorageKey(33, from), new StorageItem(new CandidateState())); + snapshot.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState { Balance = 200 })); + snapshot.Add(CreateStorageKey(33, from), new StorageItem(new CandidateState())); ret = Check_Vote(snapshot, from_Account, null, true, persistingBlock); ret.Result.Should().BeTrue(); ret.State.Should().BeTrue(); @@ -187,10 +186,10 @@ public void Check_Vote_VoteToNull() [TestMethod] public void Check_UnclaimedGas() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; - byte[] from = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); + byte[] from = Contract.GetBFTAddress(Blockchain.StandbyValidators).ToArray(); var unclaim = Check_UnclaimedGas(snapshot, from, persistingBlock); unclaim.Value.Should().Be(new BigInteger(0.5 * 1000 * 100000000L)); @@ -204,16 +203,16 @@ public void Check_UnclaimedGas() [TestMethod] public void Check_RegisterValidator() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); - var keyCount = snapshot.Storages.GetChangeSet().Count(); + var keyCount = snapshot.GetChangeSet().Count(); var point = Blockchain.StandbyValidators[0].EncodePoint(true).Clone() as byte[]; var ret = Check_RegisterValidator(snapshot, point, _persistingBlock); // Exists ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - snapshot.Storages.GetChangeSet().Count().Should().Be(++keyCount); // No changes + snapshot.GetChangeSet().Count().Should().Be(++keyCount); // No changes point[20]++; // fake point ret = Check_RegisterValidator(snapshot, point, _persistingBlock); // New @@ -221,7 +220,7 @@ public void Check_RegisterValidator() ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); // New validator + snapshot.GetChangeSet().Count().Should().Be(keyCount + 1); // New validator // Check GetRegisteredValidators @@ -232,50 +231,50 @@ public void Check_RegisterValidator() [TestMethod] public void Check_UnregisterCandidate() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); - var keyCount = snapshot.Storages.GetChangeSet().Count(); + var keyCount = snapshot.GetChangeSet().Count(); var point = Blockchain.StandbyValidators[0].EncodePoint(true); //without register var ret = Check_UnregisterCandidate(snapshot, point, _persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount); + snapshot.GetChangeSet().Count().Should().Be(keyCount); //register and then unregister ret = Check_RegisterValidator(snapshot, point, _persistingBlock); - StorageItem item = snapshot.Storages.GetAndChange(CreateStorageKey(33, point)); + StorageItem item = snapshot.GetAndChange(CreateStorageKey(33, point)); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); var members = NativeContract.NEO.GetCandidates(snapshot); Assert.AreEqual(1, members.Length); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); + snapshot.GetChangeSet().Count().Should().Be(keyCount + 1); StorageKey key = CreateStorageKey(33, point); - snapshot.Storages.TryGet(key).Should().NotBeNull(); + snapshot.TryGet(key).Should().NotBeNull(); ret = Check_UnregisterCandidate(snapshot, point, _persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount); + snapshot.GetChangeSet().Count().Should().Be(keyCount); members = NativeContract.NEO.GetCandidates(snapshot); Assert.AreEqual(0, members.Length); - snapshot.Storages.TryGet(key).Should().BeNull(); + snapshot.TryGet(key).Should().BeNull(); //register with votes, then unregister ret = Check_RegisterValidator(snapshot, point, _persistingBlock); var G_Account = Contract.CreateSignatureContract(ECCurve.Secp256r1.G).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState())); - var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable(); + snapshot.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState())); + var accountState = snapshot.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable(); accountState.Balance = 100; Check_Vote(snapshot, G_Account, Blockchain.StandbyValidators[0].ToArray(), true, _persistingBlock); ret = Check_UnregisterCandidate(snapshot, point, _persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - snapshot.Storages.TryGet(key).Should().NotBeNull(); - StorageItem pointItem = snapshot.Storages.TryGet(key); + snapshot.TryGet(key).Should().NotBeNull(); + StorageItem pointItem = snapshot.TryGet(key); CandidateState pointState = pointItem.GetInteroperable(); pointState.Registered.Should().BeFalse(); pointState.Votes.Should().Be(100); @@ -290,15 +289,15 @@ public void Check_UnregisterCandidate() [TestMethod] public void Check_GetCommittee() { - var snapshot = _snapshot.Clone(); - var keyCount = snapshot.Storages.GetChangeSet().Count(); + var snapshot = _snapshot.CreateSnapshot(); + var keyCount = snapshot.GetChangeSet().Count(); var point = Blockchain.StandbyValidators[0].EncodePoint(true); var persistingBlock = _persistingBlock; //register with votes with 20000000 var G_Account = Contract.CreateSignatureContract(ECCurve.Secp256r1.G).ScriptHash.ToArray(); - snapshot.Storages.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState())); - var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable(); + snapshot.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState())); + var accountState = snapshot.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable(); accountState.Balance = 20000000; var ret = Check_RegisterValidator(snapshot, ECCurve.Secp256r1.G.ToArray(), persistingBlock); ret.State.Should().BeTrue(); @@ -320,14 +319,20 @@ public void Check_GetCommittee() { Index = (uint)ProtocolSettings.Default.CommitteeMembersCount, Transactions = Array.Empty(), - ConsensusData = new ConsensusData() + ConsensusData = new ConsensusData(), + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + PrevHash = UInt256.Zero, + Witness = new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() } }; for (int i = 0; i < ProtocolSettings.Default.CommitteeMembersCount - 1; i++) { - Check_RegisterValidator(snapshot, Blockchain.StandbyCommittee[i].ToArray(), persistingBlock); + ret = Check_RegisterValidator(snapshot, Blockchain.StandbyCommittee[i].ToArray(), persistingBlock); + ret.State.Should().BeTrue(); + ret.Result.Should().BeTrue(); } - Check_OnPersist(snapshot, persistingBlock); + Check_OnPersist(snapshot, persistingBlock).Should().BeTrue(); committeemembers = NativeContract.NEO.GetCommittee(snapshot); committeemembers.Length.Should().Be(ProtocolSettings.Default.CommitteeMembersCount); @@ -342,13 +347,13 @@ public void Check_GetCommittee() [TestMethod] public void Check_Transfer() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block() { Index = 1000 }; - byte[] from = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); + byte[] from = Contract.GetBFTAddress(Blockchain.StandbyValidators).ToArray(); byte[] to = new byte[20]; - var keyCount = snapshot.Storages.GetChangeSet().Count(); + var keyCount = snapshot.GetChangeSet().Count(); // Check unclaim @@ -369,15 +374,15 @@ public void Check_Transfer() unclaim.Value.Should().Be(new BigInteger(0)); unclaim.State.Should().BeTrue(); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 4); // Gas + new balance + snapshot.GetChangeSet().Count().Should().Be(keyCount + 4); // Gas + new balance // Return balance - keyCount = snapshot.Storages.GetChangeSet().Count(); + keyCount = snapshot.GetChangeSet().Count(); NativeContract.NEO.Transfer(snapshot, to, from, BigInteger.One, true, persistingBlock).Should().BeTrue(); NativeContract.NEO.BalanceOf(snapshot, to).Should().Be(0); - snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount - 1); // Remove neo balance from address two + snapshot.GetChangeSet().Count().Should().Be(keyCount - 1); // Remove neo balance from address two // Bad inputs @@ -393,8 +398,8 @@ public void Check_Transfer() [TestMethod] public void Check_BalanceOf() { - var snapshot = _snapshot.Clone(); - byte[] account = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); + var snapshot = _snapshot.CreateSnapshot(); + byte[] account = Contract.GetBFTAddress(Blockchain.StandbyValidators).ToArray(); NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(100_000_000); @@ -406,10 +411,19 @@ public void Check_BalanceOf() [TestMethod] public void Check_CommitteeBonus() { - var snapshot = _snapshot.Clone(); - var persistingBlock = new Block { Index = 1, Transactions = Array.Empty() }; + var snapshot = _snapshot.CreateSnapshot(); + var persistingBlock = new Block + { + Index = 1, + Transactions = Array.Empty(), + Witness = new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() }, + ConsensusData = new ConsensusData(), + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + PrevHash = UInt256.Zero + }; - Check_PostPersist(snapshot, persistingBlock); + Check_PostPersist(snapshot, persistingBlock).Should().BeTrue(); var committee = Blockchain.StandbyCommittee; NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[0]).ScriptHash.ToArray()).Should().Be(50000000); @@ -420,7 +434,7 @@ public void Check_CommitteeBonus() [TestMethod] public void Check_Initialize() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // StandbyValidators @@ -442,70 +456,70 @@ public void Check_BadScript() [TestMethod] public void TestCalculateBonus() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block { Index = 0 }; StorageKey key = CreateStorageKey(20, UInt160.Zero.ToArray()); // Fault: balance < 0 - snapshot.Storages.Add(key, new StorageItem(new NeoAccountState + snapshot.Add(key, new StorageItem(new NeoAccountState { Balance = -100 })); Action action = () => NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); action.Should().Throw(); - snapshot.Storages.Delete(key); + snapshot.Delete(key); // Fault range: start >= end - snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState + snapshot.GetAndChange(key, () => new StorageItem(new NeoAccountState { Balance = 100, BalanceHeight = 100 })); action = () => NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); - snapshot.Storages.Delete(key); + snapshot.Delete(key); // Fault range: start >= end - snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState + snapshot.GetAndChange(key, () => new StorageItem(new NeoAccountState { Balance = 100, BalanceHeight = 100 })); action = () => NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); - snapshot.Storages.Delete(key); + snapshot.Delete(key); // Normal 1) votee is non exist - snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState + snapshot.GetAndChange(key, () => new StorageItem(new NeoAccountState { Balance = 100 })); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 100).Should().Be(new BigInteger(0.5 * 100 * 100)); - snapshot.Storages.Delete(key); + snapshot.Delete(key); // Normal 2) votee is not committee - snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState + snapshot.GetAndChange(key, () => new StorageItem(new NeoAccountState { Balance = 100, VoteTo = ECCurve.Secp256r1.G })); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 100).Should().Be(new BigInteger(0.5 * 100 * 100)); - snapshot.Storages.Delete(key); + snapshot.Delete(key); // Normal 3) votee is committee - snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState + snapshot.GetAndChange(key, () => new StorageItem(new NeoAccountState { Balance = 100, VoteTo = Blockchain.StandbyCommittee[0] })); - snapshot.Storages.Add(new KeyBuilder(-2, 23).Add(Blockchain.StandbyCommittee[0]).AddBigEndian(uint.MaxValue - 50), new StorageItem() { Value = new BigInteger(50 * 10000L).ToByteArray() }); + snapshot.Add(new KeyBuilder(NativeContract.NEO.Id, 23).Add(Blockchain.StandbyCommittee[0]).AddBigEndian(uint.MaxValue - 50), new StorageItem() { Value = new BigInteger(50 * 10000L).ToByteArray() }); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 100).Should().Be(new BigInteger(50 * 100)); - snapshot.Storages.Delete(key); + snapshot.Delete(key); } [TestMethod] @@ -529,7 +543,7 @@ public void TestGetNextBlockValidators1() [TestMethod] public void TestGetNextBlockValidators2() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var result = NativeContract.NEO.GetNextBlockValidators(snapshot); result.Length.Should().Be(7); result[0].ToArray().ToHexString().Should().Be("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70"); @@ -552,54 +566,63 @@ public void TestGetCandidates1() [TestMethod] public void TestGetCandidates2() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var result = NativeContract.NEO.GetCandidates(snapshot); result.Length.Should().Be(0); StorageKey key = NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G); - snapshot.Storages.Add(key, new StorageItem(new CandidateState())); + snapshot.Add(key, new StorageItem(new CandidateState())); NativeContract.NEO.GetCandidates(snapshot).Length.Should().Be(1); } [TestMethod] public void TestCheckCandidate() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var committee = NativeContract.NEO.GetCommittee(snapshot); var point = committee[0].EncodePoint(true); // Prepare Prefix_VoterRewardPerCommittee - var storageKey = new KeyBuilder(-2, 23).Add(committee[0]).AddBigEndian(20); - snapshot.Storages.Add(storageKey, new StorageItem(new BigInteger(1000))); + var storageKey = new KeyBuilder(NativeContract.NEO.Id, 23).Add(committee[0]).AddBigEndian(20); + snapshot.Add(storageKey, new StorageItem(new BigInteger(1000))); // Prepare Candidate - storageKey = new KeyBuilder(-2, 33).Add(committee[0]); - snapshot.Storages.Add(storageKey, new StorageItem(new CandidateState { Registered = true, Votes = BigInteger.One })); + storageKey = new KeyBuilder(NativeContract.NEO.Id, 33).Add(committee[0]); + snapshot.Add(storageKey, new StorageItem(new CandidateState { Registered = true, Votes = BigInteger.One })); - storageKey = new KeyBuilder(-2, 23).Add(committee[0]); - snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); + storageKey = new KeyBuilder(NativeContract.NEO.Id, 23).Add(committee[0]); + snapshot.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); // Pre-persist - var persistingBlock = new Block { Index = 21, ConsensusData = new ConsensusData(), Transactions = Array.Empty() }; - Check_OnPersist(snapshot, persistingBlock); + var persistingBlock = new Block + { + Index = 21, + ConsensusData = new ConsensusData(), + Transactions = Array.Empty(), + Witness = new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() }, + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + PrevHash = UInt256.Zero + }; + Check_OnPersist(snapshot, persistingBlock).Should().BeTrue(); // Clear votes - storageKey = new KeyBuilder(-2, 33).Add(committee[0]); - snapshot.Storages.GetAndChange(storageKey).GetInteroperable().Votes = BigInteger.Zero; + storageKey = new KeyBuilder(NativeContract.NEO.Id, 33).Add(committee[0]); + snapshot.GetAndChange(storageKey).GetInteroperable().Votes = BigInteger.Zero; // Unregister candidate, remove var ret = Check_UnregisterCandidate(snapshot, point, persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - storageKey = new KeyBuilder(-2, 23).Add(committee[0]); - snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(0); + storageKey = new KeyBuilder(NativeContract.NEO.Id, 23).Add(committee[0]); + snapshot.Find(storageKey.ToArray()).ToArray().Length.Should().Be(0); // Post-persist Check_PostPersist(snapshot, persistingBlock).Should().BeTrue(); - storageKey = new KeyBuilder(-2, 23).Add(committee[0]); - snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); + storageKey = new KeyBuilder(NativeContract.NEO.Id, 23).Add(committee[0]); + snapshot.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); } [TestMethod] @@ -637,7 +660,7 @@ public void TestGetCommittee() [TestMethod] public void TestGetValidators() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var result = NativeContract.NEO.ComputeNextBlockValidators(snapshot); result[0].ToArray().ToHexString().Should().Be("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70"); result[1].ToArray().ToHexString().Should().Be("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d"); @@ -667,14 +690,15 @@ public void TestOnBalanceChanging() [TestMethod] public void TestTotalSupply() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); NativeContract.NEO.TotalSupply(snapshot).Should().Be(new BigInteger(100000000)); } [TestMethod] public void TestEconomicParameter() { - var snapshot = _snapshot.Clone(); + const byte Prefix_CurrentBlock = 12; + var snapshot = _snapshot.CreateSnapshot(); var persistingBlock = new Block { Index = 0 }; (BigInteger, bool) result = Check_GetGasPerBlock(snapshot, persistingBlock); @@ -686,46 +710,56 @@ public void TestEconomicParameter() result1.Item2.Should().BeTrue(); result1.Item1.GetBoolean().Should().BeTrue(); - snapshot.BlockHashIndex.GetAndChange().Index = persistingBlock.Index + 1; + var height = snapshot[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable(); + height.Index = persistingBlock.Index + 1; result = Check_GetGasPerBlock(snapshot, persistingBlock); result.Item2.Should().BeTrue(); result.Item1.Should().Be(10 * NativeContract.GAS.Factor); // Check calculate bonus - StorageItem storage = snapshot.Storages.GetOrAdd(CreateStorageKey(20, UInt160.Zero.ToArray()), () => new StorageItem(new NeoAccountState())); + StorageItem storage = snapshot.GetOrAdd(CreateStorageKey(20, UInt160.Zero.ToArray()), () => new StorageItem(new NeoAccountState())); NeoAccountState state = storage.GetInteroperable(); state.Balance = 1000; state.BalanceHeight = 0; - snapshot.BlockHashIndex.GetAndChange().Index = 0; // Fake Height=0 + height.Index = 0; // Fake Height=0 NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, persistingBlock.Index + 2).Should().Be(6500); } [TestMethod] public void TestClaimGas() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Initialize block - snapshot.Storages.Add(CreateStorageKey(1), new StorageItem(new BigInteger(30000000))); + snapshot.Add(CreateStorageKey(1), new StorageItem(new BigInteger(30000000))); ECPoint[] standbyCommittee = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray(); CachedCommittee cachedCommittee = new CachedCommittee(); for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) { ECPoint member = standbyCommittee[i]; - snapshot.Storages.Add(new KeyBuilder(-2, 33).Add(member), new StorageItem(new CandidateState() + snapshot.Add(new KeyBuilder(NativeContract.NEO.Id, 33).Add(member), new StorageItem(new CandidateState() { Registered = true, Votes = 200 * 10000 })); cachedCommittee.Add((member, 200 * 10000)); } - snapshot.Storages[new KeyBuilder(-2, 14)].Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096); + snapshot.GetOrAdd(new KeyBuilder(NativeContract.NEO.Id, 14), () => new StorageItem()).Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096); - var item = snapshot.Storages.GetAndChange(new KeyBuilder(-2, 1), () => new StorageItem()); + var item = snapshot.GetAndChange(new KeyBuilder(NativeContract.NEO.Id, 1), () => new StorageItem()); item.Value = ((BigInteger)2100 * 10000L).ToByteArray(); - var persistingBlock = new Block { Index = 0, Transactions = Array.Empty() }; + var persistingBlock = new Block + { + Index = 0, + Transactions = Array.Empty(), + Witness = new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() }, + ConsensusData = new ConsensusData(), + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + PrevHash = UInt256.Zero + }; Check_PostPersist(snapshot, persistingBlock).Should().BeTrue(); var committee = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray(); @@ -733,36 +767,54 @@ public void TestClaimGas() var accountB = committee[ProtocolSettings.Default.CommitteeMembersCount - 1]; NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(accountA).ScriptHash).Should().Be(0); - StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(accountA).AddBigEndian(1)); + StorageItem storageItem = snapshot.TryGet(new KeyBuilder(NativeContract.NEO.Id, 23).Add(accountA).AddBigEndian(1)); new BigInteger(storageItem.Value).Should().Be(30000000000); - snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull(); + snapshot.TryGet(new KeyBuilder(NativeContract.NEO.Id, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull(); // Next block - persistingBlock = new Block { Index = 1, Transactions = Array.Empty() }; + persistingBlock = new Block + { + Index = 1, + Transactions = Array.Empty(), + Witness = new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() }, + ConsensusData = new ConsensusData(), + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + PrevHash = UInt256.Zero + }; Check_PostPersist(snapshot, persistingBlock).Should().BeTrue(); NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(committee[1]).AddBigEndian(1)); + storageItem = snapshot.TryGet(new KeyBuilder(NativeContract.NEO.Id, 23).Add(committee[1]).AddBigEndian(1)); new BigInteger(storageItem.Value).Should().Be(30000000000); // Next block - persistingBlock = new Block { Index = 21, Transactions = Array.Empty() }; + persistingBlock = new Block + { + Index = 21, + Transactions = Array.Empty(), + Witness = new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() }, + ConsensusData = new ConsensusData(), + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + PrevHash = UInt256.Zero + }; Check_PostPersist(snapshot, persistingBlock).Should().BeTrue(); accountA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[2]; NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(committee[2]).AddBigEndian(22)); + storageItem = snapshot.TryGet(new KeyBuilder(NativeContract.NEO.Id, 23).Add(committee[2]).AddBigEndian(22)); new BigInteger(storageItem.Value).Should().Be(30000000000 * 2); // Claim GAS var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; - snapshot.Storages.Add(new KeyBuilder(-2, 20).Add(account), new StorageItem(new NeoAccountState + snapshot.Add(new KeyBuilder(NativeContract.NEO.Id, 20).Add(account), new StorageItem(new NeoAccountState { BalanceHeight = 3, Balance = 200 * 10000 - 2 * 100, @@ -776,16 +828,16 @@ public void TestClaimGas() [TestMethod] public void TestUnclaimedGas() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); - snapshot.Storages.Add(CreateStorageKey(20, UInt160.Zero.ToArray()), new StorageItem(new NeoAccountState())); + snapshot.Add(CreateStorageKey(20, UInt160.Zero.ToArray()), new StorageItem(new NeoAccountState())); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); } [TestMethod] public void TestVote() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); UInt160 account = UInt160.Parse("01ff00ff00ff00ff00ff00ff00ff00ff00ff00a4"); StorageKey keyAccount = CreateStorageKey(20, account.ToArray()); StorageKey keyValidator = CreateStorageKey(33, ECCurve.Secp256r1.G.ToArray()); @@ -797,17 +849,17 @@ public void TestVote() ret.State.Should().BeTrue(); ret.Result.Should().BeFalse(); - snapshot.Storages.Add(keyAccount, new StorageItem(new NeoAccountState())); + snapshot.Add(keyAccount, new StorageItem(new NeoAccountState())); ret = Check_Vote(snapshot, account.ToArray(), ECCurve.Secp256r1.G.ToArray(), true, _persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeFalse(); - snapshot.Storages.Delete(keyAccount); - snapshot.Storages.GetAndChange(keyAccount, () => new StorageItem(new NeoAccountState + snapshot.Delete(keyAccount); + snapshot.GetAndChange(keyAccount, () => new StorageItem(new NeoAccountState { VoteTo = ECCurve.Secp256r1.G })); - snapshot.Storages.Add(keyValidator, new StorageItem(new CandidateState())); + snapshot.Add(keyValidator, new StorageItem(new CandidateState())); ret = Check_Vote(snapshot, account.ToArray(), ECCurve.Secp256r1.G.ToArray(), true, _persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); @@ -815,23 +867,23 @@ public void TestVote() internal (bool State, bool Result) Transfer4TesingOnBalanceChanging(BigInteger amount, bool addVotes) { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var engine = ApplicationEngine.Create(TriggerType.Application, Blockchain.GenesisBlock, snapshot, Blockchain.GenesisBlock); ScriptBuilder sb = new ScriptBuilder(); var tmp = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot); UInt160 from = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot)[0]; if (addVotes) { - snapshot.Storages.Add(CreateStorageKey(20, from.ToArray()), new StorageItem(new NeoAccountState + snapshot.Add(CreateStorageKey(20, from.ToArray()), new StorageItem(new NeoAccountState { VoteTo = ECCurve.Secp256r1.G, Balance = new BigInteger(1000) })); - snapshot.Storages.Add(NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G), new StorageItem(new CandidateState())); + snapshot.Add(NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G), new StorageItem(new CandidateState())); } else { - snapshot.Storages.Add(CreateStorageKey(20, from.ToArray()), new StorageItem(new NeoAccountState + snapshot.Add(CreateStorageKey(20, from.ToArray()), new StorageItem(new NeoAccountState { Balance = new BigInteger(1000) })); @@ -845,7 +897,7 @@ public void TestVote() return (true, result.GetBoolean()); } - internal static bool Check_OnPersist(StoreView snapshot, Block persistingBlock) + internal static bool Check_OnPersist(DataCache snapshot, Block persistingBlock) { var script = new ScriptBuilder(); script.EmitSysCall(ApplicationEngine.System_Contract_NativeOnPersist); @@ -855,7 +907,7 @@ internal static bool Check_OnPersist(StoreView snapshot, Block persistingBlock) return engine.Execute() == VMState.HALT; } - internal static bool Check_PostPersist(StoreView snapshot, Block persistingBlock) + internal static bool Check_PostPersist(DataCache snapshot, Block persistingBlock) { using var script = new ScriptBuilder(); script.EmitSysCall(ApplicationEngine.System_Contract_NativePostPersist); @@ -865,7 +917,7 @@ internal static bool Check_PostPersist(StoreView snapshot, Block persistingBlock return engine.Execute() == VMState.HALT; } - internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView snapshot, Block persistingBlock) + internal static (BigInteger Value, bool State) Check_GetGasPerBlock(DataCache snapshot, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, persistingBlock); engine.LoadScript(NativeContract.NEO.Script, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); @@ -885,7 +937,7 @@ internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView sn return (((VM.Types.Integer)result).GetInteger(), true); } - internal static (VM.Types.Boolean Value, bool State) Check_SetGasPerBlock(StoreView snapshot, BigInteger gasPerBlock, Block persistingBlock) + internal static (VM.Types.Boolean Value, bool State) Check_SetGasPerBlock(DataCache snapshot, BigInteger gasPerBlock, Block persistingBlock) { UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(committeeMultiSigAddr), snapshot, persistingBlock); @@ -908,7 +960,7 @@ internal static (VM.Types.Boolean Value, bool State) Check_SetGasPerBlock(StoreV return (((VM.Types.Boolean)result).GetBoolean(), true); } - internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] account, byte[] pubkey, bool signAccount, Block persistingBlock) + internal static (bool State, bool Result) Check_Vote(DataCache snapshot, byte[] account, byte[] pubkey, bool signAccount, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot, persistingBlock); @@ -936,7 +988,7 @@ internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] return (true, result.GetBoolean()); } - internal static (bool State, bool Result) Check_RegisterValidator(StoreView snapshot, byte[] pubkey, Block persistingBlock) + internal static (bool State, bool Result) Check_RegisterValidator(DataCache snapshot, byte[] pubkey, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot, persistingBlock, 1100_00000000); @@ -959,7 +1011,7 @@ internal static (bool State, bool Result) Check_RegisterValidator(StoreView snap return (true, result.GetBoolean()); } - internal static ECPoint[] Check_GetCommittee(StoreView snapshot, Block persistingBlock) + internal static ECPoint[] Check_GetCommittee(DataCache snapshot, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, persistingBlock); @@ -977,7 +1029,7 @@ internal static ECPoint[] Check_GetCommittee(StoreView snapshot, Block persistin return (result as VM.Types.Array).Select(u => u.GetSpan().AsSerializable()).ToArray(); } - internal static (BigInteger Value, bool State) Check_UnclaimedGas(StoreView snapshot, byte[] address, Block persistingBlock) + internal static (BigInteger Value, bool State) Check_UnclaimedGas(DataCache snapshot, byte[] address, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, persistingBlock); @@ -1000,7 +1052,7 @@ internal static (BigInteger Value, bool State) Check_UnclaimedGas(StoreView snap return (result.GetInteger(), true); } - internal static void CheckValidator(ECPoint eCPoint, DataCache.Trackable trackable) + internal static void CheckValidator(ECPoint eCPoint, DataCache.Trackable trackable) { var st = new BigInteger(trackable.Item.Value); st.Should().Be(0); @@ -1009,7 +1061,7 @@ internal static void CheckValidator(ECPoint eCPoint, DataCache.Trackable trackable, BigInteger balance, BigInteger height, ECPoint voteTo) + internal static void CheckBalance(byte[] account, DataCache.Trackable trackable, BigInteger balance, BigInteger height, ECPoint voteTo) { var st = (VM.Types.Struct)BinarySerializer.Deserialize(trackable.Item.Value, 16, 32); @@ -1036,7 +1088,7 @@ internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) return storageKey; } - internal static (bool State, bool Result) Check_UnregisterCandidate(StoreView snapshot, byte[] pubkey, Block persistingBlock) + internal static (bool State, bool Result) Check_UnregisterCandidate(DataCache snapshot, byte[] pubkey, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot, persistingBlock); diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index d0dee61fc8..c84807442b 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -7,6 +7,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.UnitTests.Extensions; +using Neo.UnitTests.IO.Caching; using System; using System.Linq; @@ -15,7 +16,7 @@ namespace Neo.UnitTests.SmartContract.Native [TestClass] public class UT_PolicyContract { - private StoreView _snapshot; + private DataCache _snapshot; [TestInitialize] public void TestSetup() @@ -30,7 +31,7 @@ public void TestSetup() [TestMethod] public void Check_Default() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); var ret = NativeContract.Policy.Call(snapshot, "getMaxTransactionsPerBlock"); ret.Should().BeOfType(); @@ -52,13 +53,11 @@ public void Check_Default() [TestMethod] public void Check_SetMaxBlockSize() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); - UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); // Without signature @@ -99,12 +98,11 @@ public void Check_SetMaxBlockSize() [TestMethod] public void Check_SetMaxBlockSystemFee() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); @@ -146,12 +144,11 @@ public void Check_SetMaxBlockSystemFee() [TestMethod] public void Check_SetMaxTransactionsPerBlock() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new TrimmedBlock() { NextConsensus = UInt160.Zero }); // Without signature @@ -179,12 +176,11 @@ public void Check_SetMaxTransactionsPerBlock() [TestMethod] public void Check_SetFeePerByte() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new TrimmedBlock() { NextConsensus = UInt160.Zero }); // Without signature @@ -217,8 +213,6 @@ public void Check_SetBaseExecFee() // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); - NativeContract.Policy.Initialize(ApplicationEngine.Create(TriggerType.Application, null, snapshot, block, 0)); // Without signature @@ -263,8 +257,6 @@ public void Check_SetStoragePrice() // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); - NativeContract.Policy.Initialize(ApplicationEngine.Create(TriggerType.Application, null, snapshot, block, 0)); // Without signature @@ -304,12 +296,11 @@ public void Check_SetStoragePrice() [TestMethod] public void Check_BlockAccount() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new TrimmedBlock() { NextConsensus = UInt160.Zero }); // Without signature @@ -353,13 +344,11 @@ public void Check_BlockAccount() [TestMethod] public void Check_Block_UnblockAccount() { - var snapshot = _snapshot.Clone(); + var snapshot = _snapshot.CreateSnapshot(); // Fake blockchain Block block = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new TrimmedBlock() { NextConsensus = UInt160.Zero }); - UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); // Block without signature diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs b/tests/neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs index 24db8906f5..d4088258f8 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs @@ -16,7 +16,7 @@ namespace Neo.UnitTests.SmartContract.Native [TestClass] public class UT_RoleManagement { - private StoreView _snapshot; + private DataCache _snapshot; [TestInitialize] public void TestSetup() @@ -28,7 +28,7 @@ public void TestSetup() [TestMethod] public void TestSetAndGet() { - var snapshot1 = _snapshot.Clone(); + var snapshot1 = _snapshot.CreateSnapshot(); UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot1); ECPoint[] validators = NativeContract.NEO.ComputeNextBlockValidators(snapshot1); var ret = NativeContract.RoleManagement.Call( @@ -40,7 +40,7 @@ public void TestSetAndGet() new ContractParameter(ContractParameterType.Array) { Value = validators.Select(p => new ContractParameter(ContractParameterType.ByteArray) { Value = p.ToArray() }).ToList() } ); snapshot1.Commit(); - var snapshot2 = _snapshot.Clone(); + var snapshot2 = _snapshot.CreateSnapshot(); ret = NativeContract.RoleManagement.Call( snapshot2, "getDesignatedByRole", diff --git a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs index ad8e37b107..ce0cbf9677 100644 --- a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs +++ b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs @@ -63,7 +63,7 @@ public void TestCanResetAppEngineProviderTwice() class TestProvider : IApplicationEngineProvider { - public ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, Block persistingBlock, long gas) + public ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, long gas) { return new TestEngine(trigger, container, snapshot, persistingBlock, gas); } @@ -71,7 +71,7 @@ public ApplicationEngine Create(TriggerType trigger, IVerifiable container, Stor class TestEngine : ApplicationEngine { - public TestEngine(TriggerType trigger, IVerifiable container, StoreView snapshot, Block persistingBlock, long gas) + public TestEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, long gas) : base(trigger, container, snapshot, persistingBlock, gas) { } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs index 53b8f559af..24c9907029 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -61,7 +61,7 @@ public void ApplicationEngineRegularPut() StorageItem sItem = TestUtils.GetStorageItem(new byte[0] { }); var snapshot = Blockchain.Singleton.GetSnapshot(); - snapshot.Storages.Add(skey, sItem); + snapshot.Add(skey, sItem); snapshot.AddContract(script.ToScriptHash(), contractState); using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) @@ -94,7 +94,7 @@ public void ApplicationEngineReusedStorage_FullReuse() StorageItem sItem = TestUtils.GetStorageItem(value); var snapshot = Blockchain.Singleton.GetSnapshot(); - snapshot.Storages.Add(skey, sItem); + snapshot.Add(skey, sItem); snapshot.AddContract(script.ToScriptHash(), contractState); using (ApplicationEngine applicationEngine = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) @@ -129,7 +129,7 @@ public void ApplicationEngineReusedStorage_PartialReuse() StorageItem sItem = TestUtils.GetStorageItem(oldValue); var snapshot = Blockchain.Singleton.GetSnapshot(); - snapshot.Storages.Add(skey, sItem); + snapshot.Add(skey, sItem); snapshot.AddContract(script.ToScriptHash(), contractState); using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) @@ -165,7 +165,7 @@ public void ApplicationEngineReusedStorage_PartialReuseTwice() StorageItem sItem = TestUtils.GetStorageItem(oldValue); var snapshot = Blockchain.Singleton.GetSnapshot(); - snapshot.Storages.Add(skey, sItem); + snapshot.Add(skey, sItem); snapshot.AddContract(script.ToScriptHash(), contractState); using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index d268840d64..d721c3936a 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -114,7 +114,7 @@ public void TestAccount_IsStandard() 0x01, 0x01, 0x01, 0x01, 0x01 }; engine.IsStandardContract(new UInt160(hash)).Should().BeFalse(); - var snapshot = Blockchain.Singleton.GetSnapshot(); + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); var state = TestUtils.GetContract(); snapshot.AddContract(state.Hash, state); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); @@ -130,7 +130,7 @@ public void TestAccount_IsStandard() [TestMethod] public void TestContract_Create() { - var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); var nef = new NefFile() { Script = new byte[byte.MaxValue], @@ -173,7 +173,7 @@ public void TestContract_Create() [TestMethod] public void TestContract_Update() { - var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); var nef = new NefFile() { Script = new byte[] { 0x01 }, @@ -211,11 +211,11 @@ public void TestContract_Update() Key = new byte[] { 0x01 } }; snapshot.AddContract(state.Hash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); state.UpdateCounter.Should().Be(0); snapshot.UpdateContract(state.Hash, nef.ToArray(), manifest.ToJson().ToByteArray(false)); var ret = NativeContract.ContractManagement.GetContract(snapshot, state.Hash); - snapshot.Storages.Find(BitConverter.GetBytes(state.Id)).ToList().Count().Should().Be(1); + snapshot.Find(BitConverter.GetBytes(state.Id)).ToList().Count().Should().Be(1); ret.UpdateCounter.Should().Be(1); ret.Id.Should().Be(state.Id); ret.Manifest.ToJson().ToString().Should().Be(manifest.ToJson().ToString()); @@ -233,7 +233,7 @@ public void TestContract_Update_Invalid() }; nefFile.CheckSum = NefFile.ComputeChecksum(nefFile); - var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); Assert.ThrowsException(() => snapshot.UpdateContract(null, null, new byte[] { 0x01 })); Assert.ThrowsException(() => snapshot.UpdateContract(null, nefFile.ToArray(), null)); @@ -254,7 +254,7 @@ public void TestContract_Update_Invalid() [TestMethod] public void TestStorage_Find() { - var snapshot = Blockchain.Singleton.GetSnapshot(); + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); var state = TestUtils.GetContract(); var storageItem = new StorageItem @@ -268,7 +268,7 @@ public void TestStorage_Find() Key = new byte[] { 0x01 } }; snapshot.AddContract(state.Hash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index d5e70f1a23..2ef9ac2de8 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -8,6 +8,7 @@ using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; using Neo.UnitTests.Extensions; using Neo.VM; using Neo.VM.Types; @@ -183,7 +184,7 @@ public void Runtime_GetNotifications_Test() snapshot.DeleteContract(scriptHash2); } - private void AssertNotification(StackItem stackItem, UInt160 scriptHash, string notification) + private static void AssertNotification(StackItem stackItem, UInt160 scriptHash, string notification) { Assert.IsInstanceOfType(stackItem, typeof(VM.Types.Array)); @@ -259,10 +260,10 @@ public void TestRuntime_CheckWitness() engine.CheckWitness(pubkey.EncodePoint(true)).Should().BeTrue(); engine.CheckWitness(((Transaction)engine.ScriptContainer).Sender.ToArray()).Should().BeTrue(); - ((Transaction)engine.ScriptContainer).Signers = new Signer[0]; + ((Transaction)engine.ScriptContainer).Signers = System.Array.Empty(); engine.CheckWitness(pubkey.EncodePoint(true)).Should().BeFalse(); - Action action = () => engine.CheckWitness(new byte[0]); + Action action = () => engine.CheckWitness(System.Array.Empty()); action.Should().Throw(); } @@ -336,7 +337,8 @@ public void TestCrypto_Verify() [TestMethod] public void TestBlockchain_GetHeight() { - GetEngine(true, true).GetBlockchainHeight().Should().Be(0); + var engine = GetEngine(true, true); + NativeContract.Ledger.CurrentIndex(engine.Snapshot).Should().Be(0); } [TestMethod] @@ -344,16 +346,16 @@ public void TestBlockchain_GetBlock() { var engine = GetEngine(true, true); - engine.GetBlock(new byte[] { 0x01 }).Should().BeNull(); + NativeContract.Ledger.GetBlock(engine.Snapshot, UInt256.Zero).Should().BeNull(); byte[] data1 = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; - engine.GetBlock(data1).Should().BeNull(); + NativeContract.Ledger.GetBlock(engine.Snapshot, new UInt256(data1)).Should().BeNull(); byte[] data2 = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; - Assert.ThrowsException(() => engine.GetBlock(data2)); + Assert.ThrowsException(() => NativeContract.Ledger.GetBlock(engine.Snapshot, new UInt256(data2))); } [TestMethod] @@ -364,18 +366,31 @@ public void TestBlockchain_GetTransaction() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; - engine.GetTransaction(new UInt256(data1)).Should().BeNull(); + NativeContract.Ledger.GetTransaction(engine.Snapshot, new UInt256(data1)).Should().BeNull(); } [TestMethod] public void TestBlockchain_GetTransactionHeight() { - var engine = GetEngine(true, true); - byte[] data1 = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; - engine.GetTransactionHeight(new UInt256(data1)).Should().Be(-1); + var engine = GetEngine(hasSnapshot: true, addScript: false); + var state = new TransactionState() + { + BlockIndex = 0, + Transaction = TestUtils.CreateRandomHashTransaction() + }; + UT_SmartContractHelper.TransactionAdd(engine.Snapshot, state); + engine.LoadScript(NativeContract.Ledger.Script, configureState: p => p.ScriptHash = NativeContract.Ledger.Hash); + + var script = new ScriptBuilder(); + script.EmitPush(state.Transaction.Hash.ToArray()); + script.EmitPush("getTransactionHeight"); + engine.LoadScript(script.ToArray()); + engine.Execute(); + Assert.AreEqual(engine.State, VMState.HALT); + + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Integer)); + result.GetInteger().Should().Be(0); } [TestMethod] @@ -386,14 +401,14 @@ public void TestBlockchain_GetContract() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; - Neo.SmartContract.Native.NativeContract.ContractManagement.GetContract(engine.Snapshot, new UInt160(data1)).Should().BeNull(); + NativeContract.ContractManagement.GetContract(engine.Snapshot, new UInt160(data1)).Should().BeNull(); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); snapshot.AddContract(state.Hash, state); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - Neo.SmartContract.Native.NativeContract.ContractManagement.GetContract(engine.Snapshot, state.Hash).Should().BeSameAs(state); + NativeContract.ContractManagement.GetContract(engine.Snapshot, state.Hash).Should().BeSameAs(state); } [TestMethod] @@ -434,7 +449,7 @@ public void TestStorage_Get() IsConstant = true }; snapshot.AddContract(state.Hash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); @@ -491,7 +506,7 @@ public void TestStorage_Put() IsConstant = true }; snapshot.AddContract(state.Hash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); key = new byte[] { 0x01 }; @@ -505,7 +520,7 @@ public void TestStorage_Put() //value length == 0 key = new byte[] { 0x01 }; - value = new byte[0]; + value = System.Array.Empty(); engine.Put(storageContext, key, value); } @@ -525,7 +540,7 @@ public void TestStorage_PutEx() IsConstant = false }; snapshot.AddContract(state.Hash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); var key = new byte[] { 0x01 }; @@ -555,7 +570,7 @@ public void TestStorage_Delete() IsConstant = false }; snapshot.AddContract(state.Hash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); var key = new byte[] { 0x01 }; @@ -612,7 +627,7 @@ public void TestContract_Call() [TestMethod] public void TestContract_Destroy() { - var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); var scriptHash = UInt160.Parse("0xcb9f3b7c6fb1cf2c13a40637c189bdd066a272b4"); var storageItem = new StorageItem @@ -627,15 +642,15 @@ public void TestContract_Destroy() Key = new byte[] { 0x01 } }; snapshot.AddContract(scriptHash, state); - snapshot.Storages.Add(storageKey, storageItem); + snapshot.Add(storageKey, storageItem); snapshot.DestroyContract(scriptHash); - snapshot.Storages.Find(BitConverter.GetBytes(0x43000000)).Any().Should().BeFalse(); + snapshot.Find(BitConverter.GetBytes(0x43000000)).Any().Should().BeFalse(); //storages are removed state = TestUtils.GetContract(); snapshot.AddContract(scriptHash, state); snapshot.DestroyContract(scriptHash); - snapshot.Storages.Find(BitConverter.GetBytes(0x43000000)).Any().Should().BeFalse(); + snapshot.Find(BitConverter.GetBytes(0x43000000)).Any().Should().BeFalse(); } [TestMethod] @@ -655,7 +670,7 @@ public static void LogEvent(object sender, LogEventArgs args) private static ApplicationEngine GetEngine(bool hasContainer = false, bool hasSnapshot = false, bool hasBlock = false, bool addScript = true, long gas = 20_00000000) { var tx = hasContainer ? TestUtils.GetTransaction(UInt160.Zero) : null; - var snapshot = hasSnapshot ? Blockchain.Singleton.GetSnapshot().Clone() : null; + var snapshot = hasSnapshot ? Blockchain.Singleton.GetSnapshot() : null; var block = hasBlock ? new Block() : null; ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot, block, gas); if (addScript) engine.LoadScript(new byte[] { 0x01 }); diff --git a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs index a23513f2a2..970f29720a 100644 --- a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs @@ -1,7 +1,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.UnitTests.Extensions; using Neo.Wallets; using System; @@ -14,6 +17,10 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_SmartContractHelper { + const byte Prefix_Block = 5; + const byte Prefix_BlockHash = 9; + const byte Prefix_Transaction = 11; + [TestInitialize] public void TestSetup() { @@ -116,17 +123,34 @@ public void TestIsStandardContract() [TestMethod] public void TestVerifyWitnesses() { - var snapshot1 = Blockchain.Singleton.GetSnapshot(); + var snapshot1 = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); UInt256 index1 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); - snapshot1.Blocks.Add(index1, new TrimmedBlock()); - snapshot1.Blocks.Delete(index1); + BlocksAdd(snapshot1, index1, new TrimmedBlock() + { + Timestamp = 1, + PrevHash = UInt256.Zero, + MerkleRoot = UInt256.Zero, + ConsensusData = new ConsensusData(), + Hashes = new UInt256[1] { UInt256.Zero }, + NextConsensus = UInt160.Zero, + Witness = new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] } + }); + BlocksDelete(snapshot1, index1); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(new Header() { PrevHash = index1 }, snapshot1, 100)); var snapshot2 = Blockchain.Singleton.GetSnapshot(); UInt256 index2 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); - TrimmedBlock block2 = new TrimmedBlock(); - block2.NextConsensus = UInt160.Zero; - snapshot2.Blocks.Add(index2, block2); + TrimmedBlock block2 = new TrimmedBlock() + { + Timestamp = 2, + PrevHash = UInt256.Zero, + MerkleRoot = UInt256.Zero, + ConsensusData = new ConsensusData(), + Hashes = new UInt256[1] { UInt256.Zero }, + NextConsensus = UInt160.Zero, + Witness = new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] } + }; + BlocksAdd(snapshot2, index2, block2); Header header2 = new Header() { PrevHash = index2, Witness = new Witness { VerificationScript = new byte[0] } }; snapshot2.AddContract(UInt160.Zero, new ContractState()); @@ -135,9 +159,17 @@ public void TestVerifyWitnesses() var snapshot3 = Blockchain.Singleton.GetSnapshot(); UInt256 index3 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); - TrimmedBlock block3 = new TrimmedBlock(); - block3.NextConsensus = UInt160.Zero; - snapshot3.Blocks.Add(index3, block3); + TrimmedBlock block3 = new TrimmedBlock() + { + Timestamp = 3, + PrevHash = UInt256.Zero, + MerkleRoot = UInt256.Zero, + ConsensusData = new ConsensusData(), + Hashes = new UInt256[1] { UInt256.Zero }, + NextConsensus = UInt160.Zero, + Witness = new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] } + }; + BlocksAdd(snapshot3, index3, block3); Header header3 = new Header() { PrevHash = index3, @@ -164,12 +196,32 @@ public void TestVerifyWitnesses() Manifest = TestUtils.CreateManifest("verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 }; snapshot3.AddContract(contract.Hash, contract); - var tx = new Extensions.Nep17NativeContractExtensions.ManualWitness(contract.Hash) + var tx = new Nep17NativeContractExtensions.ManualWitness(contract.Hash) { - Witnesses = new Witness[] { new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] } } + Witnesses = new Witness[] { new Witness() { InvocationScript = Array.Empty(), VerificationScript = Array.Empty() } } }; Assert.AreEqual(true, Neo.SmartContract.Helper.VerifyWitnesses(tx, snapshot3, 1000)); } + + private void BlocksDelete(DataCache snapshot, UInt256 hash) + { + snapshot.Delete(NativeContract.Ledger.CreateStorageKey(Prefix_BlockHash, hash)); + snapshot.Delete(NativeContract.Ledger.CreateStorageKey(Prefix_Block, hash)); + } + + public static void TransactionAdd(DataCache snapshot, params TransactionState[] txs) + { + foreach (TransactionState tx in txs) + { + snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Transaction, tx.Transaction.Hash), new StorageItem(tx, true)); + } + } + + public static void BlocksAdd(DataCache snapshot, UInt256 hash, TrimmedBlock block) + { + snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_BlockHash, block.Index), new StorageItem(hash.ToArray(), true)); + snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Block, hash), new StorageItem(block.ToArray(), true)); + } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index ed7abb463e..7ce2aed12c 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -3,6 +3,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.UnitTests.Extensions; using Neo.VM; using Neo.VM.Types; @@ -36,7 +37,7 @@ public void System_Blockchain_GetBlock() Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, }; - var block = new Block() + var block = new TrimmedBlock() { Index = 0, Timestamp = 2, @@ -50,15 +51,14 @@ public void System_Blockchain_GetBlock() MerkleRoot = UInt256.Zero, NextConsensus = UInt160.Zero, ConsensusData = new ConsensusData() { Nonce = 1, PrimaryIndex = 1 }, - Transactions = new Transaction[] { tx } + Hashes = new UInt256[] { new ConsensusData() { Nonce = 1, PrimaryIndex = 1 }.Hash, tx.Hash } }; - var snapshot = Blockchain.Singleton.GetSnapshot(); + var snapshot = Blockchain.Singleton.GetSnapshot().CreateSnapshot(); using (var script = new ScriptBuilder()) { - script.EmitPush(block.Hash.ToArray()); - script.EmitSysCall(ApplicationEngine.System_Blockchain_GetBlock); + script.EmitDynamicCall(NativeContract.Ledger.Hash, "getBlock", block.Hash.ToArray()); // Without block @@ -71,13 +71,18 @@ public void System_Blockchain_GetBlock() // Not traceable block - var height = snapshot.BlockHashIndex.GetAndChange(); + const byte Prefix_Transaction = 11; + const byte Prefix_CurrentBlock = 12; + + var height = snapshot[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable(); height.Index = block.Index + ProtocolSettings.Default.MaxTraceableBlocks; - var blocks = snapshot.Blocks; - var txs = snapshot.Transactions; - blocks.Add(block.Hash, block.Trim()); - txs.Add(tx.Hash, new TransactionState() { Transaction = tx, BlockIndex = block.Index, VMState = VMState.HALT }); + UT_SmartContractHelper.BlocksAdd(snapshot, block.Hash, block); + snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Transaction, tx.Hash), new StorageItem(new TransactionState + { + BlockIndex = block.Index, + Transaction = tx + }, true)); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(script.ToArray()); @@ -98,11 +103,6 @@ public void System_Blockchain_GetBlock() var array = engine.ResultStack.Pop(); Assert.AreEqual(block.Hash, new UInt256(array[0].GetSpan())); - - // Clean - - blocks.Delete(block.Hash); - txs.Delete(tx.Hash); } } @@ -316,7 +316,7 @@ public void System_Runtime_GasLeft() public void System_Runtime_GetInvocationCounter() { ContractState contractA, contractB, contractC; - var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + var snapshot = Blockchain.Singleton.GetSnapshot(); // Create dummy contracts diff --git a/tests/neo.UnitTests/TestUtils.cs b/tests/neo.UnitTests/TestUtils.cs index e85b2e653c..76646ef3f9 100644 --- a/tests/neo.UnitTests/TestUtils.cs +++ b/tests/neo.UnitTests/TestUtils.cs @@ -55,13 +55,16 @@ public static ContractManifest CreateManifest(string method, ContractParameterTy return manifest; } - public static StorageKey CreateStorageKey(this NativeContract contract, byte prefix, ISerializable key) + public static StorageKey CreateStorageKey(this NativeContract contract, byte prefix, ISerializable key = null) { - return new StorageKey - { - Id = contract.Id, - Key = key.ToArray().Prepend(prefix).ToArray() - }; + var k = new KeyBuilder(contract.Id, prefix); + if (key != null) k = k.Add(key); + return k; + } + + public static StorageKey CreateStorageKey(this NativeContract contract, byte prefix, uint value) + { + return new KeyBuilder(contract.Id, prefix).AddBigEndian(value); } public static byte[] GetByteArray(int length, byte firstByte) diff --git a/tests/neo.UnitTests/TestVerifiable.cs b/tests/neo.UnitTests/TestVerifiable.cs index 7959eeec3b..5f98f07f2a 100644 --- a/tests/neo.UnitTests/TestVerifiable.cs +++ b/tests/neo.UnitTests/TestVerifiable.cs @@ -27,7 +27,7 @@ public void DeserializeUnsigned(BinaryReader reader) throw new NotImplementedException(); } - public UInt160[] GetScriptHashesForVerifying(StoreView snapshot) + public UInt160[] GetScriptHashesForVerifying(DataCache snapshot) { throw new NotImplementedException(); } diff --git a/tests/neo.UnitTests/UT_DataCache.cs b/tests/neo.UnitTests/UT_DataCache.cs index 22bcdaa26d..b10747df8d 100644 --- a/tests/neo.UnitTests/UT_DataCache.cs +++ b/tests/neo.UnitTests/UT_DataCache.cs @@ -1,6 +1,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using Neo.Ledger; +using Neo.Persistence; +using Neo.SmartContract; using System.Linq; namespace Neo.UnitTests @@ -18,8 +20,8 @@ public void TestSetup() public void TestCachedFind_Between() { var snapshot = Blockchain.Singleton.GetSnapshot(); - var storages = snapshot.Storages.CreateSnapshot(); - var cache = new CloneCache(storages); + var storages = snapshot.CreateSnapshot(); + var cache = new ClonedCache(storages); storages.Add ( @@ -57,8 +59,8 @@ public void TestCachedFind_Between() public void TestCachedFind_Last() { var snapshot = Blockchain.Singleton.GetSnapshot(); - var storages = snapshot.Storages.CreateSnapshot(); - var cache = new CloneCache(storages); + var storages = snapshot.CreateSnapshot(); + var cache = new ClonedCache(storages); storages.Add ( @@ -89,8 +91,8 @@ public void TestCachedFind_Last() public void TestCachedFind_Empty() { var snapshot = Blockchain.Singleton.GetSnapshot(); - var storages = snapshot.Storages.CreateSnapshot(); - var cache = new CloneCache(storages); + var storages = snapshot.CreateSnapshot(); + var cache = new ClonedCache(storages); cache.Add ( diff --git a/tests/neo.UnitTests/VM/UT_Helper.cs b/tests/neo.UnitTests/VM/UT_Helper.cs index c012d4917a..a903fead4a 100644 --- a/tests/neo.UnitTests/VM/UT_Helper.cs +++ b/tests/neo.UnitTests/VM/UT_Helper.cs @@ -158,7 +158,7 @@ public void TestMakeScript() { byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); - Assert.AreEqual("0c14000000000000000000000000000000000000000011c01f0c0962616c616e63654f660c143d2f0bce7a4d9bb50b95425a71f444eb3045847541627d5b52", + Assert.AreEqual("0c14000000000000000000000000000000000000000011c01f0c0962616c616e63654f660c1428b3adab7269f9c2181db3cb741ebf551930e27041627d5b52", testScript.ToHexString()); } diff --git a/tests/neo.UnitTests/Wallets/UT_Wallet.cs b/tests/neo.UnitTests/Wallets/UT_Wallet.cs index da87f3148c..219bd62d25 100644 --- a/tests/neo.UnitTests/Wallets/UT_Wallet.cs +++ b/tests/neo.UnitTests/Wallets/UT_Wallet.cs @@ -202,13 +202,13 @@ public void TestGetAvailable() // Fake balance var snapshot = Blockchain.Singleton.GetSnapshot(); var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); wallet.GetAvailable(NativeContract.GAS.Hash).Should().Be(new BigDecimal(1000000000000, 8)); - entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 0; snapshot.Commit(); } @@ -224,14 +224,14 @@ public void TestGetBalance() // Fake balance var snapshot = Blockchain.Singleton.GetSnapshot(); var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); wallet.GetBalance(UInt160.Zero, new UInt160[] { account.ScriptHash }).Should().Be(new BigDecimal(0, 0)); wallet.GetBalance(NativeContract.GAS.Hash, new UInt160[] { account.ScriptHash }).Should().Be(new BigDecimal(1000000000000, 8)); - entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 0; snapshot.Commit(); } @@ -327,11 +327,11 @@ public void TestMakeTransaction1() // Fake balance var snapshot = Blockchain.Singleton.GetSnapshot(); var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); - var entry1 = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry1 = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry1.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; key = NativeContract.NEO.CreateStorageKey(20, account.ScriptHash); - var entry2 = snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoToken.NeoAccountState())); + var entry2 = snapshot.GetAndChange(key, () => new StorageItem(new NeoToken.NeoAccountState())); entry2.GetInteroperable().Balance = 10000 * NativeContract.NEO.Factor; snapshot.Commit(); @@ -359,8 +359,8 @@ public void TestMakeTransaction1() }); tx.Should().NotBeNull(); - entry1 = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); - entry2 = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + entry1 = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); + entry2 = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry1.GetInteroperable().Balance = 0; entry2.GetInteroperable().Balance = 0; snapshot.Commit(); @@ -380,7 +380,7 @@ public void TestMakeTransaction2() // Fake balance var snapshot = Blockchain.Singleton.GetSnapshot(); var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 1000000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -395,7 +395,7 @@ public void TestMakeTransaction2() tx = wallet.MakeTransaction(new byte[] { }, null, null, Array.Empty()); tx.Should().NotBeNull(); - entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState())); + entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); entry.GetInteroperable().Balance = 0; snapshot.Commit(); }