From f9eae5aca1a23b682992c17a8a0f420f790e1a23 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Sat, 18 Apr 2020 18:14:54 +0800 Subject: [PATCH] Simplify access to storage for native contracts. --- src/neo/IO/Caching/DataCache.cs | 4 +- src/neo/Ledger/ContractState.cs | 5 + src/neo/Ledger/StorageItem.cs | 46 ++++++++- src/neo/Network/P2P/Payloads/Block.cs | 5 + src/neo/Network/P2P/Payloads/Transaction.cs | 5 + src/neo/SmartContract/IInteroperable.cs | 1 + .../SmartContract/Native/Tokens/NeoToken.cs | 68 ++++--------- .../Native/Tokens/Nep5AccountState.cs | 29 +----- .../SmartContract/Native/Tokens/Nep5Token.cs | 43 ++------ tests/neo.UnitTests/Ledger/UT_Blockchain.cs | 11 +-- .../Network/P2P/Payloads/UT_Transaction.cs | 99 ++++--------------- .../Native/Tokens/UT_NeoToken.cs | 87 ++++------------ tests/neo.UnitTests/Wallets/UT_Wallet.cs | 85 +++------------- 13 files changed, 154 insertions(+), 334 deletions(-) diff --git a/src/neo/IO/Caching/DataCache.cs b/src/neo/IO/Caching/DataCache.cs index 4529978a19..d20d1bba2e 100644 --- a/src/neo/IO/Caching/DataCache.cs +++ b/src/neo/IO/Caching/DataCache.cs @@ -219,7 +219,7 @@ public TValue GetAndChange(TKey key, Func factory = null) { if (trackable.State == TrackState.Deleted) { - if (factory == null) throw new KeyNotFoundException(); + if (factory == null) return null; trackable.Item = factory(); trackable.State = TrackState.Changed; } @@ -237,7 +237,7 @@ public TValue GetAndChange(TKey key, Func factory = null) }; if (trackable.Item == null) { - if (factory == null) throw new KeyNotFoundException(); + if (factory == null) return null; trackable.Item = factory(); trackable.State = TrackState.Added; } diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index a47a6366f7..504175ee4b 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -58,6 +58,11 @@ void ICloneable.FromReplica(ContractState replica) Manifest = replica.Manifest.Clone(); } + void IInteroperable.FromStackItem(StackItem stackItem) + { + throw new NotSupportedException(); + } + void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Id); diff --git a/src/neo/Ledger/StorageItem.cs b/src/neo/Ledger/StorageItem.cs index 49ea93d8a1..801f0c72a0 100644 --- a/src/neo/Ledger/StorageItem.cs +++ b/src/neo/Ledger/StorageItem.cs @@ -1,15 +1,48 @@ using Neo.IO; +using Neo.SmartContract; using System.IO; namespace Neo.Ledger { public class StorageItem : ICloneable, ISerializable { - public byte[] Value; + private byte[] value; + private IInteroperable interoperable; public bool IsConstant; public int Size => Value.GetVarSize() + sizeof(bool); + public byte[] Value + { + get + { + if (value is null && interoperable != null) + value = BinarySerializer.Serialize(interoperable.ToStackItem(null), 4096); + return value; + } + set + { + interoperable = null; + this.value = value; + } + } + + public StorageItem() + { + } + + public StorageItem(byte[] value, bool isConstant = false) + { + this.value = value; + this.IsConstant = isConstant; + } + + public StorageItem(IInteroperable interoperable, bool isConstant = false) + { + this.interoperable = interoperable; + this.IsConstant = isConstant; + } + StorageItem ICloneable.Clone() { return new StorageItem @@ -31,6 +64,17 @@ void ICloneable.FromReplica(StorageItem replica) IsConstant = replica.IsConstant; } + public T GetInteroperable() where T : IInteroperable, new() + { + if (interoperable is null) + { + interoperable = new T(); + interoperable.FromStackItem(BinarySerializer.Deserialize(value, 16, 34)); + } + value = null; + return (T)interoperable; + } + public void Serialize(BinaryWriter writer) { writer.WriteVarBytes(Value); diff --git a/src/neo/Network/P2P/Payloads/Block.cs b/src/neo/Network/P2P/Payloads/Block.cs index a3623a4c94..2663eb28f4 100644 --- a/src/neo/Network/P2P/Payloads/Block.cs +++ b/src/neo/Network/P2P/Payloads/Block.cs @@ -81,6 +81,11 @@ 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(); diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 6035ac2285..48b65b02cd 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -195,6 +195,11 @@ public override bool Equals(object obj) return Equals(obj as Transaction); } + void IInteroperable.FromStackItem(StackItem stackItem) + { + throw new NotSupportedException(); + } + public override int GetHashCode() { return Hash.GetHashCode(); diff --git a/src/neo/SmartContract/IInteroperable.cs b/src/neo/SmartContract/IInteroperable.cs index 41807cd10a..ec53ef48c0 100644 --- a/src/neo/SmartContract/IInteroperable.cs +++ b/src/neo/SmartContract/IInteroperable.cs @@ -5,6 +5,7 @@ namespace Neo.SmartContract { public interface IInteroperable { + void FromStackItem(StackItem stackItem); StackItem ToStackItem(ReferenceCounter referenceCounter); } } diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index ef633ad597..4c9147220e 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -44,9 +44,8 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco if (state.VoteTo != null) { StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate, state.VoteTo.ToArray())); - CandidateState state_validator = CandidateState.FromByteArray(storage_validator.Value); + CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes += amount; - storage_validator.Value = state_validator.ToByteArray(); } } @@ -55,7 +54,6 @@ private void DistributeGas(ApplicationEngine engine, UInt160 account, AccountSta BigInteger gas = CalculateBonus(engine.Snapshot, state.Balance, state.BalanceHeight, engine.Snapshot.PersistingBlock.Index); state.BalanceHeight = engine.Snapshot.PersistingBlock.Index; GAS.Mint(engine, account, gas); - engine.Snapshot.Storages.GetAndChange(CreateAccountKey(account)).Value = state.ToByteArray(); } private BigInteger CalculateBonus(StoreView snapshot, BigInteger value, uint start, uint end) @@ -130,7 +128,7 @@ public BigInteger UnclaimedGas(StoreView snapshot, UInt160 account, uint end) { StorageItem storage = snapshot.Storages.TryGet(CreateAccountKey(account)); if (storage is null) return BigInteger.Zero; - AccountState state = new AccountState(storage.Value); + AccountState state = storage.GetInteroperable(); return CalculateBonus(snapshot, state.Balance, state.BalanceHeight, end); } @@ -146,13 +144,9 @@ private StackItem RegisterCandidate(ApplicationEngine engine, Array args) private bool RegisterCandidate(StoreView snapshot, ECPoint pubkey) { StorageKey key = CreateStorageKey(Prefix_Candidate, pubkey); - StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new CandidateState().ToByteArray() - }); - CandidateState state = CandidateState.FromByteArray(item.Value); + StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem(new CandidateState())); + CandidateState state = item.GetInteroperable(); state.Registered = true; - item.Value = state.ToByteArray(); return true; } @@ -170,16 +164,11 @@ private bool UnregisterCandidate(StoreView snapshot, ECPoint pubkey) StorageKey key = CreateStorageKey(Prefix_Candidate, pubkey); if (snapshot.Storages.TryGet(key) is null) return true; StorageItem item = snapshot.Storages.GetAndChange(key); - CandidateState state = CandidateState.FromByteArray(item.Value); + CandidateState state = item.GetInteroperable(); if (state.Votes.IsZero) - { snapshot.Storages.Delete(key); - } else - { state.Registered = false; - item.Value = state.ToByteArray(); - } return true; } @@ -197,29 +186,25 @@ private bool Vote(StoreView snapshot, UInt160 account, ECPoint voteTo) StorageKey key_account = CreateAccountKey(account); if (snapshot.Storages.TryGet(key_account) is null) return false; StorageItem storage_account = snapshot.Storages.GetAndChange(key_account); - AccountState state_account = new AccountState(storage_account.Value); + AccountState state_account = storage_account.GetInteroperable(); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate, state_account.VoteTo.ToArray()); StorageItem storage_validator = snapshot.Storages.GetAndChange(key); - CandidateState state_validator = CandidateState.FromByteArray(storage_validator.Value); + CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; if (!state_validator.Registered && state_validator.Votes.IsZero) snapshot.Storages.Delete(key); - else - storage_validator.Value = state_validator.ToByteArray(); } state_account.VoteTo = voteTo; - storage_account.Value = state_account.ToByteArray(); if (voteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate, voteTo.ToArray()); if (snapshot.Storages.TryGet(key) is null) return false; StorageItem storage_validator = snapshot.Storages.GetAndChange(key); - CandidateState state_validator = CandidateState.FromByteArray(storage_validator.Value); + CandidateState state_validator = storage_validator.GetInteroperable(); if (!state_validator.Registered) return false; state_validator.Votes += state_account.Balance; - storage_validator.Value = state_validator.ToByteArray(); } return true; } @@ -236,7 +221,7 @@ public IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetCandidates(StoreVie return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), - CandidateState.FromByteArray(p.Value.Value) + p.Value.GetInteroperable() )).Where(p => p.Item2.Registered).Select(p => (p.Item1, p.Item2.Votes)); } @@ -285,49 +270,38 @@ public class AccountState : Nep5AccountState public uint BalanceHeight; public ECPoint VoteTo; - public AccountState() - { - } - - public AccountState(byte[] data) - : base(data) - { - } - - protected override void FromStruct(Struct @struct) + public override void FromStackItem(StackItem stackItem) { - base.FromStruct(@struct); + base.FromStackItem(stackItem); + Struct @struct = (Struct)stackItem; BalanceHeight = (uint)@struct[1].GetBigInteger(); VoteTo = @struct[2].IsNull ? null : @struct[2].GetSpan().AsSerializable(); } - protected override Struct ToStruct() + public override StackItem ToStackItem(ReferenceCounter referenceCounter) { - Struct @struct = base.ToStruct(); + Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add(BalanceHeight); @struct.Add(VoteTo?.ToArray() ?? StackItem.Null); return @struct; } } - internal class CandidateState + internal class CandidateState : IInteroperable { public bool Registered = true; public BigInteger Votes; - public static CandidateState FromByteArray(byte[] data) + public void FromStackItem(StackItem stackItem) { - Struct @struct = (Struct)BinarySerializer.Deserialize(data, 16, 32); - return new CandidateState - { - Registered = @struct[0].ToBoolean(), - Votes = @struct[1].GetBigInteger() - }; + Struct @struct = (Struct)stackItem; + Registered = @struct[0].ToBoolean(); + Votes = @struct[1].GetBigInteger(); } - public byte[] ToByteArray() + public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return BinarySerializer.Serialize(new Struct { Registered, Votes }, 32); + return new Struct(referenceCounter) { Registered, Votes }; } } } diff --git a/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs b/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs index b2d62be6d1..cb46d0bd94 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs @@ -4,37 +4,18 @@ namespace Neo.SmartContract.Native.Tokens { - public class Nep5AccountState + public class Nep5AccountState : IInteroperable { public BigInteger Balance; - public Nep5AccountState() + public virtual void FromStackItem(StackItem stackItem) { + Balance = ((Struct)stackItem)[0].GetBigInteger(); } - public Nep5AccountState(byte[] data) + public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) { - FromByteArray(data); - } - - public void FromByteArray(byte[] data) - { - FromStruct((Struct)BinarySerializer.Deserialize(data, 16, 34)); - } - - protected virtual void FromStruct(Struct @struct) - { - Balance = @struct[0].GetBigInteger(); - } - - public byte[] ToByteArray() - { - return BinarySerializer.Serialize(ToStruct(), 4096); - } - - protected virtual Struct ToStruct() - { - return new Struct(new StackItem[] { Balance }); + return new Struct(referenceCounter) { Balance }; } } } diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index 3e331de487..b4e389676f 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -70,15 +70,10 @@ 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(CreateAccountKey(account), () => new StorageItem - { - Value = new TState().ToByteArray() - }); - TState state = new TState(); - state.FromByteArray(storage.Value); + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateAccountKey(account), () => new StorageItem(new TState())); + TState state = storage.GetInteroperable(); OnBalanceChanging(engine, account, state, amount); state.Balance += amount; - storage.Value = state.ToByteArray(); storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem { Value = BigInteger.Zero.ToByteArrayStandard() @@ -95,19 +90,13 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, if (amount.IsZero) return; StorageKey key = CreateAccountKey(account); StorageItem storage = engine.Snapshot.Storages.GetAndChange(key); - TState state = new TState(); - state.FromByteArray(storage.Value); + 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); - } else - { state.Balance -= amount; - storage.Value = state.ToByteArray(); - } storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); BigInteger totalSupply = new BigInteger(storage.Value); totalSupply -= amount; @@ -156,8 +145,7 @@ public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account) { StorageItem storage = snapshot.Storages.TryGet(CreateAccountKey(account)); if (storage is null) return BigInteger.Zero; - Nep5AccountState state = new Nep5AccountState(storage.Value); - return state.Balance; + return storage.GetInteroperable().Balance; } [ContractMethod(0_08000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Hash160, ContractParameterType.Integer }, ParameterNames = new[] { "from", "to", "amount" })] @@ -177,21 +165,19 @@ protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 ContractState contract_to = engine.Snapshot.Contracts.TryGet(to); if (contract_to?.Payable == false) return false; StorageKey key_from = CreateAccountKey(from); - StorageItem storage_from = engine.Snapshot.Storages.TryGet(key_from); + StorageItem storage_from = engine.Snapshot.Storages.GetAndChange(key_from); if (amount.IsZero) { if (storage_from != null) { - TState state_from = new TState(); - state_from.FromByteArray(storage_from.Value); + TState state_from = storage_from.GetInteroperable(); OnBalanceChanging(engine, from, state_from, amount); } } else { if (storage_from is null) return false; - TState state_from = new TState(); - state_from.FromByteArray(storage_from.Value); + TState state_from = storage_from.GetInteroperable(); if (state_from.Balance < amount) return false; if (from.Equals(to)) { @@ -201,25 +187,14 @@ 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); - } else - { state_from.Balance -= amount; - storage_from = engine.Snapshot.Storages.GetAndChange(key_from); - storage_from.Value = state_from.ToByteArray(); - } StorageKey key_to = CreateAccountKey(to); - StorageItem storage_to = engine.Snapshot.Storages.GetAndChange(key_to, () => new StorageItem - { - Value = new TState().ToByteArray() - }); - TState state_to = new TState(); - state_to.FromByteArray(storage_to.Value); + StorageItem storage_to = engine.Snapshot.Storages.GetAndChange(key_to, () => new StorageItem(new TState())); + TState state_to = storage_to.GetInteroperable(); OnBalanceChanging(engine, to, state_to, amount); state_to.Balance += amount; - storage_to.Value = state_to.ToByteArray(); } } engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", from.ToArray(), to.ToArray(), amount })); diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs index cf421b99cf..b38c71e2a5 100644 --- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs +++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs @@ -113,16 +113,9 @@ public void TestValidTransaction() // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 100_000_000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 100_000_000 * NativeContract.GAS.Factor; snapshot.Commit(); diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index adee349b2b..4fc2f9cc4a 100644 --- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -107,16 +107,9 @@ public void FeeIsMultiSigContract() // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -184,16 +177,9 @@ public void FeeIsSignatureContractDetailed() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -302,16 +288,9 @@ public void FeeIsSignatureContract_TestScope_Global() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -395,16 +374,9 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -489,16 +461,9 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -586,16 +551,9 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; // Make transaction // Manually creating script @@ -644,16 +602,9 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); @@ -743,16 +694,9 @@ public void FeeIsSignatureContract_TestScope_NoScopeFAULT() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; // Make transaction // Manually creating script @@ -1001,16 +945,9 @@ public void FeeIsSignatureContract_TestScope_Global_Default() var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); - var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index b2696b4888..6d26b5d9ef 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -238,23 +238,17 @@ public void TestCalculateBonus() { var snapshot = Blockchain.Singleton.GetSnapshot(); StorageKey key = CreateStorageKey(20, UInt160.Zero.ToArray()); - snapshot.Storages.Add(key, new StorageItem + snapshot.Storages.Add(key, new StorageItem(new AccountState { - Value = new AccountState() - { - Balance = -100 - }.ToByteArray() - }); + Balance = -100 + })); Action action = () => NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); action.Should().Throw(); snapshot.Storages.Delete(key); - snapshot.Storages.GetAndChange(key, () => new StorageItem + snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState { - Value = new AccountState() - { - Balance = 100 - }.ToByteArray() - }); + Balance = 100 + })); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 30 * Blockchain.DecrementInterval).Should().Be(new BigInteger(7000000000)); } @@ -345,10 +339,7 @@ public void TestGetRegisteredValidators2() result[6].Votes.Should().Be(new BigInteger(1785714)); StorageKey key = NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G); - snapshot.Storages.Add(key, new StorageItem - { - Value = new CandidateState().ToByteArray() - }); + snapshot.Storages.Add(key, new StorageItem(new CandidateState())); NativeContract.NEO.GetCandidates(snapshot).ToArray().Length.Should().Be(22); } @@ -429,10 +420,7 @@ public void TestUnclaimedGas() { var snapshot = Blockchain.Singleton.GetSnapshot(); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); - snapshot.Storages.Add(CreateStorageKey(20, UInt160.Zero.ToArray()), new StorageItem - { - Value = new AccountState().ToByteArray() - }); + snapshot.Storages.Add(CreateStorageKey(20, UInt160.Zero.ToArray()), new StorageItem(new AccountState())); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); } @@ -451,46 +439,22 @@ public void TestVote() ret.State.Should().BeTrue(); ret.Result.Should().BeFalse(); - snapshot.Storages.Add(keyAccount, new StorageItem - { - Value = new AccountState().ToByteArray() - }); + snapshot.Storages.Add(keyAccount, new StorageItem(new AccountState())); ret = Check_Vote(snapshot, account.ToArray(), ECCurve.Secp256r1.G.ToArray(), true); ret.State.Should().BeTrue(); ret.Result.Should().BeFalse(); snapshot.Storages.Delete(keyAccount); - snapshot.Storages.GetAndChange(keyAccount, () => new StorageItem + snapshot.Storages.GetAndChange(keyAccount, () => new StorageItem(new AccountState { - Value = new AccountState() - { - VoteTo = ECCurve.Secp256r1.G - }.ToByteArray() - }); - snapshot.Storages.Add(keyValidator, new StorageItem - { - Value = new CandidateState().ToByteArray() - }); + VoteTo = ECCurve.Secp256r1.G + })); + snapshot.Storages.Add(keyValidator, new StorageItem(new CandidateState())); ret = Check_Vote(snapshot, account.ToArray(), ECCurve.Secp256r1.G.ToArray(), true); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); } - [TestMethod] - public void TestValidatorState_FromByteArray() - { - CandidateState input = new CandidateState { Votes = new BigInteger(1000) }; - CandidateState output = CandidateState.FromByteArray(input.ToByteArray()); - output.Should().BeEquivalentTo(input); - } - - [TestMethod] - public void TestValidatorState_ToByteArray() - { - CandidateState input = new CandidateState { Votes = new BigInteger(1000) }; - input.ToByteArray().ToHexString().Should().Be("410220012102e803"); - } - internal (bool State, bool Result) Transfer4TesingOnBalanceChanging(BigInteger amount, bool addVotes) { var snapshot = Blockchain.Singleton.GetSnapshot(); @@ -501,28 +465,19 @@ public void TestValidatorState_ToByteArray() UInt160 from = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot)[0]; if (addVotes) { - snapshot.Storages.Add(CreateStorageKey(20, from.ToArray()), new StorageItem - { - Value = new AccountState() - { - VoteTo = ECCurve.Secp256r1.G, - Balance = new BigInteger(1000) - }.ToByteArray() - }); - snapshot.Storages.Add(NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G), new StorageItem + snapshot.Storages.Add(CreateStorageKey(20, from.ToArray()), new StorageItem(new AccountState { - Value = new CandidateState().ToByteArray() - }); + VoteTo = ECCurve.Secp256r1.G, + Balance = new BigInteger(1000) + })); + snapshot.Storages.Add(NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G), new StorageItem(new CandidateState())); } else { - snapshot.Storages.Add(CreateStorageKey(20, from.ToArray()), new StorageItem + snapshot.Storages.Add(CreateStorageKey(20, from.ToArray()), new StorageItem(new AccountState { - Value = new AccountState() - { - Balance = new BigInteger(1000) - }.ToByteArray() - }); + Balance = new BigInteger(1000) + })); } sb.EmitAppCall(NativeContract.NEO.Hash, "transfer", from, UInt160.Zero, amount); diff --git a/tests/neo.UnitTests/Wallets/UT_Wallet.cs b/tests/neo.UnitTests/Wallets/UT_Wallet.cs index 15a1cc8844..63ddb327fe 100644 --- a/tests/neo.UnitTests/Wallets/UT_Wallet.cs +++ b/tests/neo.UnitTests/Wallets/UT_Wallet.cs @@ -203,24 +203,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 - { - Value = new Nep5AccountState().ToByteArray() - }); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); + entry.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); wallet.GetAvailable(NativeContract.GAS.Hash).Should().Be(new BigDecimal(1000000000000, 8)); - entry.Value = new Nep5AccountState() - { - Balance = 0 - } - .ToByteArray(); + entry.GetInteroperable().Balance = 0; snapshot.Commit(); } @@ -235,25 +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 - { - Value = new Nep5AccountState().ToByteArray() - }); - entry.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); + 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.Value = new Nep5AccountState() - { - Balance = 0 - } - .ToByteArray(); + entry.GetInteroperable().Balance = 0; snapshot.Commit(); } @@ -345,26 +323,12 @@ 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 - { - Value = new Nep5AccountState().ToByteArray() - }); - entry1.Value = new Nep5AccountState() - { - Balance = 10000 * NativeContract.GAS.Factor - } - .ToByteArray(); + var entry1 = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); + entry1.GetInteroperable().Balance = 10000 * NativeContract.GAS.Factor; key = NativeContract.NEO.CreateStorageKey(20, account.ScriptHash); - var entry2 = snapshot.Storages.GetAndChange(key, () => new StorageItem - { - Value = new Nep5AccountState().ToByteArray() - }); - entry2.Value = new NeoToken.AccountState() - { - Balance = 10000 * NativeContract.NEO.Factor - } - .ToByteArray(); + var entry2 = snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoToken.AccountState())); + entry2.GetInteroperable().Balance = 10000 * NativeContract.NEO.Factor; snapshot.Commit(); @@ -390,16 +354,8 @@ public void TestMakeTransaction1() }); tx.Should().NotBeNull(); - entry1.Value = new Nep5AccountState() - { - Balance = 0 - } - .ToByteArray(); - entry2.Value = new NeoToken.AccountState() - { - Balance = 0 - } - .ToByteArray(); + entry1.GetInteroperable().Balance = 0; + entry2.GetInteroperable().Balance = 0; snapshot.Commit(); } @@ -417,15 +373,8 @@ 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 - { - Value = new Nep5AccountState().ToByteArray() - }); - entry.Value = new Nep5AccountState() - { - Balance = 1000000 * NativeContract.GAS.Factor - } - .ToByteArray(); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); + entry.GetInteroperable().Balance = 1000000 * NativeContract.GAS.Factor; snapshot.Commit(); var tx = wallet.MakeTransaction(new byte[] { }, account.ScriptHash, new TransactionAttribute[] { }); @@ -434,11 +383,7 @@ public void TestMakeTransaction2() tx = wallet.MakeTransaction(new byte[] { }, null, new TransactionAttribute[] { }); tx.Should().NotBeNull(); - entry.Value = new NeoToken.AccountState() - { - Balance = 0 - } - .ToByteArray(); + entry.GetInteroperable().Balance = 0; snapshot.Commit(); }