From bc785f3f0a7af9be31686c4cd80f1170a345da2f Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 18 Aug 2020 08:40:35 +0800 Subject: [PATCH 01/60] add reward key --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index aa8ea6da75..887e112f1c 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -27,6 +27,8 @@ public sealed class NeoToken : Nep5Token private const byte Prefix_Candidate = 33; private const byte Prefix_NextValidators = 14; + private const byte Prefix_VoterRewardPerCommittee = 23; + internal NeoToken() { this.TotalAmount = 100000000 * Factor; From a6e438efc568465e9c2aa5b981642826f9b90b7a Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sat, 22 Aug 2020 22:05:29 +0800 Subject: [PATCH 02/60] incentive for voter --- .../SmartContract/Native/Tokens/NeoToken.cs | 62 +++++++++++++++++-- .../Native/Tokens/UT_NeoToken.cs | 2 +- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index f51603e28c..70c978d11d 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -58,16 +58,35 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco private void DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) { - BigInteger gas = CalculateBonus(engine.Snapshot, state.Balance, state.BalanceHeight, engine.Snapshot.PersistingBlock.Index); + BigInteger gas = CalculateBonus(engine.Snapshot, state.VoteTo, state.Balance, state.BalanceHeight, engine.Snapshot.PersistingBlock.Index); state.BalanceHeight = engine.Snapshot.PersistingBlock.Index; GAS.Mint(engine, account, gas); } - private BigInteger CalculateBonus(StoreView snapshot, BigInteger value, uint start, uint end) + private BigInteger CalculateBonus(StoreView 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)); + BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); + if (vote is null) return neoHolderReward; + + var keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).Add(uint.MaxValue - end - 1); + var keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).Add(uint.MaxValue - start - 1); + var enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator(); + if (!enumerator.MoveNext()) return neoHolderReward; + var endRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); + var startRewardPerNeo = BigInteger.Zero; + var keyMax = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).Add(uint.MaxValue); + enumerator = snapshot.Storages.FindRange(keyEnd, keyMax).GetEnumerator(); + if (enumerator.MoveNext()) + startRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); + + return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 10000L; + } + + private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value, uint start, uint end) + { GasRecord gasRecord = snapshot.Storages[CreateStorageKey(Prefix_GasPerBlock)].GetInteroperable(); BigInteger sum = 0; for (var i = gasRecord.Count - 1; i >= 0; i--) @@ -108,15 +127,32 @@ protected override void OnPersist(ApplicationEngine engine) // Distribute GAS for committee var gasPerBlock = GetGasPerBlock(engine.Snapshot); - var committee = GetCommitteeMembers(engine.Snapshot).ToArray(); + var committee = GetCommittee(engine.Snapshot); var pubkey = committee[engine.Snapshot.PersistingBlock.Index % ProtocolSettings.Default.CommitteeMembersCount]; var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); + // Record the cumulative GAS of the voters + + var voterRewardPerCommittee = gasPerBlock * VoterRewardRatio / 100 / (ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount); + (ECPoint, BigInteger)[] committeeVotes = GetCommitteeVotes(engine.Snapshot); + for (var i = 0; i < committeeVotes.Length; i++) + { + if (committeeVotes[i].Item2 > 0) + { + BigInteger voterRewardPerNEO = (i < ProtocolSettings.Default.ValidatorsCount ? 2 : 1) * voterRewardPerCommittee * 10000L / committeeVotes[i].Item2; // Zoom in 10000 times, and the final calculation should be divided 10000L + var enumerator = engine.Snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].Item1).ToArray()).GetEnumerator(); + if (enumerator.MoveNext()) + voterRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); + var storageKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].Item1).Add(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + engine.Snapshot.Storages.Add(storageKey, new StorageItem() { Value = voterRewardPerNEO.ToByteArray() }); + } + } + // Set next validators StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_NextValidators), () => new StorageItem()); - storage.Value = committee[..ProtocolSettings.Default.ValidatorsCount].ToByteArray(); + storage.Value = GetValidators(engine.Snapshot).ToByteArray(); } [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] @@ -153,7 +189,7 @@ public BigInteger UnclaimedGas(StoreView snapshot, UInt160 account, uint end) StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; NeoAccountState state = storage.GetInteroperable(); - return CalculateBonus(snapshot, state.Balance, state.BalanceHeight, end); + return CalculateBonus(snapshot, state.VoteTo, state.Balance, state.BalanceHeight, end); } [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] @@ -251,6 +287,22 @@ public UInt160 GetCommitteeAddress(StoreView snapshot) return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); } + private (ECPoint PublicKey, BigInteger Votes)[] GetCommitteeVotes(StoreView snapshot) + { + (ECPoint PublicKey, BigInteger Votes)[] committeeVotes = new (ECPoint PublicKey, BigInteger Votes)[ProtocolSettings.Default.CommitteeMembersCount]; + var i = 0; + foreach (var commiteePubKey in GetCommitteeMembers(snapshot)) + { + var item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(commiteePubKey)); + if (item is null) + committeeVotes[i] = (commiteePubKey, BigInteger.Zero); + else + committeeVotes[i] = (commiteePubKey, item.GetInteroperable().Votes); + i++; + } + return committeeVotes; + } + private IEnumerable GetCommitteeMembers(StoreView snapshot) { decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index e723092325..ff01759e92 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -404,7 +404,7 @@ public void Check_CommitteeBonus() engine.Execute(); engine.State.Should().Be(VM.VMState.HALT); - var committee = Blockchain.StandbyCommittee; + var committee = NativeContract.NEO.GetCommittee(engine.Snapshot); NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[0]).ScriptHash.ToArray()).Should().Be(25000000); NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash.ToArray()).Should().Be(0); } From 4249d07a0d6365f31d58c59eb2af3698c3874ddf Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sat, 22 Aug 2020 22:44:19 +0800 Subject: [PATCH 03/60] optimize --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 70c978d11d..b6ca6ff596 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -51,8 +51,15 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco if (amount.IsZero) return; if (state.VoteTo != null) { - engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(state.VoteTo)).GetInteroperable().Votes += amount; + CandidateState state_validator = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(state.VoteTo)).GetInteroperable(); + state_validator.Votes += amount; engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); + + if (state_validator.Votes == 0) + { + foreach (var (key, _) in engine.Snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(state.VoteTo).ToArray())) + engine.Snapshot.Storages.Delete(key); + } } } @@ -248,7 +255,14 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; if (!state_validator.Registered && state_validator.Votes.IsZero) + { + DistributeGas(engine, account, state_account); + UInt160 voteeAddr = Contract.CreateSignatureContract(state_account.VoteTo).ScriptHash; + foreach (var (rewardKey, _) in engine.Snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteeAddr).ToArray())) + engine.Snapshot.Storages.Delete(rewardKey); + engine.Snapshot.Storages.Delete(key); + } } state_account.VoteTo = voteTo; if (validator_new != null) From 422f20ab3927d3c987b7164c5512295c288d406f Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sun, 23 Aug 2020 08:13:47 +0800 Subject: [PATCH 04/60] optimize --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index b6ca6ff596..51a3ca6dcb 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -139,20 +139,21 @@ protected override void OnPersist(ApplicationEngine engine) var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); - // Record the cumulative GAS of the voters + // Record the cumulative reward of the voters of each committee var voterRewardPerCommittee = gasPerBlock * VoterRewardRatio / 100 / (ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount); - (ECPoint, BigInteger)[] committeeVotes = GetCommitteeVotes(engine.Snapshot); + (ECPoint PublickKey, BigInteger Votes)[] committeeVotes = GetCommitteeVotes(engine.Snapshot); for (var i = 0; i < committeeVotes.Length; i++) { if (committeeVotes[i].Item2 > 0) { - BigInteger voterRewardPerNEO = (i < ProtocolSettings.Default.ValidatorsCount ? 2 : 1) * voterRewardPerCommittee * 10000L / committeeVotes[i].Item2; // Zoom in 10000 times, and the final calculation should be divided 10000L - var enumerator = engine.Snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].Item1).ToArray()).GetEnumerator(); + BigInteger voterSumRewardPerNEO = (i < ProtocolSettings.Default.ValidatorsCount ? 2 : 1) * voterRewardPerCommittee * 10000L / committeeVotes[i].Votes; // Zoom in 10000 times, and the final calculation should be divided 10000L + byte[] voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey).ToArray(); + var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix).GetEnumerator(); if (enumerator.MoveNext()) - voterRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var storageKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].Item1).Add(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); - engine.Snapshot.Storages.Add(storageKey, new StorageItem() { Value = voterRewardPerNEO.ToByteArray() }); + voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); + var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey).Add(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } From df0062baa690fd5b3775ede23e1b5214b25819f9 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sun, 23 Aug 2020 08:40:27 +0800 Subject: [PATCH 05/60] optimize --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 51a3ca6dcb..559eecb6df 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -148,11 +148,11 @@ protected override void OnPersist(ApplicationEngine engine) if (committeeVotes[i].Item2 > 0) { BigInteger voterSumRewardPerNEO = (i < ProtocolSettings.Default.ValidatorsCount ? 2 : 1) * voterRewardPerCommittee * 10000L / committeeVotes[i].Votes; // Zoom in 10000 times, and the final calculation should be divided 10000L - byte[] voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey).ToArray(); - var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix).GetEnumerator(); + var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey); + var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey).Add(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + var voterRewardKey = voterRewardKeyPrefix.Add(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } From 7c72d41fde09b332bb5df75075ee3506c4bc76ae Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sun, 23 Aug 2020 12:32:02 +0800 Subject: [PATCH 06/60] fix CalculateBonus and add ut --- .../SmartContract/Native/Tokens/NeoToken.cs | 8 +- .../Native/Tokens/UT_NeoToken.cs | 127 ++++++++++++++++++ 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 559eecb6df..d2b3a9e1fc 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -78,13 +78,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; - var keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).Add(uint.MaxValue - end - 1); - var keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).Add(uint.MaxValue - start - 1); + var keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); + var keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); var enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator(); if (!enumerator.MoveNext()) return neoHolderReward; var endRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); var startRewardPerNeo = BigInteger.Zero; - var keyMax = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).Add(uint.MaxValue); + var keyMax = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue); enumerator = snapshot.Storages.FindRange(keyEnd, keyMax).GetEnumerator(); if (enumerator.MoveNext()) startRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); @@ -152,7 +152,7 @@ protected override void OnPersist(ApplicationEngine engine) var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = voterRewardKeyPrefix.Add(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index ff01759e92..4f607b0bea 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -1,5 +1,6 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Consensus; using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; @@ -11,6 +12,7 @@ using Neo.SmartContract.Native; using Neo.UnitTests.Extensions; using Neo.VM; +using Neo.Wallets; using System; using System.Linq; using System.Numerics; @@ -460,6 +462,16 @@ public void TestCalculateBonus() action = () => NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 10).Should().Be(new BigInteger(0)); snapshot.Storages.Delete(key); + // Fault range: start >= end + + snapshot.Storages.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); + // Normal 1) votee is non exist snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState @@ -468,6 +480,27 @@ public void TestCalculateBonus() })); NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 100).Should().Be(new BigInteger(0.5 * 100 * 100)); snapshot.Storages.Delete(key); + + // Normal 2) votee is not committee + + snapshot.Storages.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); + + // Normal 3) votee is committee + + snapshot.Storages.GetAndChange(key, () => new StorageItem(new NeoAccountState + { + Balance = 100, + VoteTo = Blockchain.StandbyCommittee[0] + })); + snapshot.Storages.Add(new KeyBuilder(-1, 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(100 * 100)); + snapshot.Storages.Delete(key); } [TestMethod] @@ -602,6 +635,82 @@ public void TestEconomicParameter() result1.Item1.GetBoolean().Should().BeTrue(); } + [TestMethod] + public void TestClaimGas() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + + // Initialize block + + for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) + { + ECPoint member = Blockchain.StandbyCommittee[i]; + var moreVotes = 0; + if (i < ProtocolSettings.Default.ValidatorsCount) + moreVotes += 10; + snapshot.Storages.Add(new KeyBuilder(-1, 33).Add(member), new StorageItem(new CandidateState() + { + Registered = true, + Votes = 100 * 10000 + moreVotes + })); + } + var item = snapshot.Storages.GetAndChange(new KeyBuilder(-1, 1), () => new StorageItem()); + item.Value = ((BigInteger)2100 * 10000L).ToByteArray(); + + snapshot.PersistingBlock = new Block { Index = 0 }; + Check_OnPersist(snapshot).Should().BeTrue(); + + for(var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) + { + ECPoint member = Blockchain.StandbyCommittee[i]; + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1)); + if (i < ProtocolSettings.Default.ValidatorsCount) + new BigInteger(storageItem.Value).Should().Be(303568); + else + new BigInteger(storageItem.Value).Should().Be(151785); + } + + // Next block + + snapshot.PersistingBlock = new Block { Index = 1 }; + Check_OnPersist(snapshot).Should().BeTrue(); + for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) + { + ECPoint member = Blockchain.StandbyCommittee[i]; + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1 - 1)); + if (i < ProtocolSettings.Default.ValidatorsCount) + new BigInteger(storageItem.Value).Should().Be(303568 * 2); + else + new BigInteger(storageItem.Value).Should().Be(151785 * 2); + } + + // Next block + + snapshot.PersistingBlock = new Block { Index = 2 }; + Check_OnPersist(snapshot).Should().BeTrue(); + for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) + { + ECPoint member = Blockchain.StandbyCommittee[i]; + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1 - 2)); + if (i < ProtocolSettings.Default.ValidatorsCount) + new BigInteger(storageItem.Value).Should().Be(303568 * 3); + else + new BigInteger(storageItem.Value).Should().Be(151785 * 3); + } + + // Claim GAS + + var account = Contract.CreateSignatureContract(Blockchain.StandbyCommittee[0]).ScriptHash; + snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState + { + BalanceHeight = 1, + Balance = 100, + VoteTo = Blockchain.StandbyCommittee[0] + })); + BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2); + value.Should().Be(3085); + } + [TestMethod] public void TestUnclaimedGas() { @@ -675,6 +784,24 @@ public void TestVote() return (true, result.GetBoolean()); } + internal static bool Check_OnPersist(StoreView snapshot) + { + ECPoint[] committees = NativeContract.NEO.GetCommittee(snapshot); + UInt160 committeesMultisign = Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); + var engine = ApplicationEngine.Create(TriggerType.System, + new Nep5NativeContractExtensions.ManualWitness(committeesMultisign), snapshot); + + engine.LoadScript(NativeContract.NEO.Script); + + var script = new ScriptBuilder(); + script.EmitPush(0); + script.Emit(OpCode.PACK); + script.EmitPush("onPersist"); + engine.LoadScript(script.ToArray()); + + return engine.Execute() == VMState.HALT; + } + internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); From 0a3d09e0ad2a5c7cb8f331d4e3cb3ae72a352bec Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sun, 23 Aug 2020 12:36:25 +0800 Subject: [PATCH 07/60] format --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index d2b3a9e1fc..641bfd4097 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -79,7 +79,7 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v if (vote is null) return neoHolderReward; var keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); - var keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); + var keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); var enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator(); if (!enumerator.MoveNext()) return neoHolderReward; var endRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 4f607b0bea..02bc94a175 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -660,7 +660,7 @@ public void TestClaimGas() snapshot.PersistingBlock = new Block { Index = 0 }; Check_OnPersist(snapshot).Should().BeTrue(); - for(var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) + for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) { ECPoint member = Blockchain.StandbyCommittee[i]; StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1)); From 723f60c4b1782749370dfbc787e69dcbb0da8250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?= Date: Sun, 23 Aug 2020 09:55:53 -0300 Subject: [PATCH 08/60] Item2 -> Votes --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 641bfd4097..80648b52a0 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -145,7 +145,7 @@ protected override void OnPersist(ApplicationEngine engine) (ECPoint PublickKey, BigInteger Votes)[] committeeVotes = GetCommitteeVotes(engine.Snapshot); for (var i = 0; i < committeeVotes.Length; i++) { - if (committeeVotes[i].Item2 > 0) + if (committeeVotes[i].Votes > 0) { BigInteger voterSumRewardPerNEO = (i < ProtocolSettings.Default.ValidatorsCount ? 2 : 1) * voterRewardPerCommittee * 10000L / committeeVotes[i].Votes; // Zoom in 10000 times, and the final calculation should be divided 10000L var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey); From 5b92e05d28d0810c3995984f02c2eeecc0de2d49 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Tue, 25 Aug 2020 17:55:22 +0800 Subject: [PATCH 09/60] Move fields --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index e003866659..2b0d94d87f 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -28,13 +28,12 @@ public sealed class NeoToken : Nep5Token private const byte Prefix_Candidate = 33; private const byte Prefix_NextValidators = 14; private const byte Prefix_GasPerBlock = 29; + private const byte Prefix_VoterRewardPerCommittee = 23; private const byte NeoHolderRewardRatio = 10; private const byte CommitteeRewardRatio = 5; private const byte VoterRewardRatio = 85; - private const byte Prefix_VoterRewardPerCommittee = 23; - internal NeoToken() { this.TotalAmount = 100000000 * Factor; From addfebfe77570f9b2b7d06037ab6ebb94cc5eb61 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Tue, 25 Aug 2020 19:01:22 +0800 Subject: [PATCH 10/60] Fix GetCommitteeVotes() --- .../SmartContract/Native/Tokens/NeoToken.cs | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 2b0d94d87f..b961bafc5d 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -142,17 +142,17 @@ protected override void OnPersist(ApplicationEngine engine) // Record the cumulative reward of the voters of each committee var voterRewardPerCommittee = gasPerBlock * VoterRewardRatio / 100 / (ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount); - (ECPoint PublickKey, BigInteger Votes)[] committeeVotes = GetCommitteeVotes(engine.Snapshot); + var committeeVotes = GetCommitteeVotes(engine.Snapshot).ToArray(); for (var i = 0; i < committeeVotes.Length; i++) { if (committeeVotes[i].Votes > 0) { BigInteger voterSumRewardPerNEO = (i < ProtocolSettings.Default.ValidatorsCount ? 2 : 1) * voterRewardPerCommittee * 10000L / committeeVotes[i].Votes; // Zoom in 10000 times, and the final calculation should be divided 10000L - var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey); + var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublicKey); var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublickKey).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[i].PublicKey).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } @@ -273,15 +273,29 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) return true; } + private CandidateState GetCandidate(StoreView snapshot, ECPoint pubkey) + { + StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); + return snapshot.Storages.TryGet(key)?.GetInteroperable(); + } + [ContractMethod(1_00000000, CallFlags.AllowStates)] public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(StoreView snapshot) + { + return GetCandidatesInternal(snapshot) + .Where(p => p.State.Registered) + .Select(p => (p.PublicKey, p.State.Votes)) + .ToArray(); + } + + private (ECPoint PublicKey, CandidateState State)[] GetCandidatesInternal(StoreView snapshot) { byte[] prefix_key = CreateStorageKey(Prefix_Candidate).ToArray(); return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), p.Value.GetInteroperable() - )).Where(p => p.Item2.Registered).Select(p => (p.Item1, p.Item2.Votes)).ToArray(); + )).ToArray(); } [ContractMethod(1_00000000, CallFlags.AllowStates)] @@ -302,22 +316,6 @@ public UInt160 GetCommitteeAddress(StoreView snapshot) return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); } - private (ECPoint PublicKey, BigInteger Votes)[] GetCommitteeVotes(StoreView snapshot) - { - (ECPoint PublicKey, BigInteger Votes)[] committeeVotes = new (ECPoint PublicKey, BigInteger Votes)[ProtocolSettings.Default.CommitteeMembersCount]; - var i = 0; - foreach (var commiteePubKey in GetCommitteeMembers(snapshot)) - { - var item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(commiteePubKey)); - if (item is null) - committeeVotes[i] = (commiteePubKey, BigInteger.Zero); - else - committeeVotes[i] = (commiteePubKey, item.GetInteroperable().Votes); - i++; - } - return committeeVotes; - } - private IEnumerable GetCommitteeMembers(StoreView snapshot) { decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; @@ -330,6 +328,24 @@ private IEnumerable GetCommitteeMembers(StoreView snapshot) return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } + private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetCommitteeVotes(StoreView snapshot) + { + decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; + decimal VoterTurnout = votersCount / (decimal)TotalAmount; + if (VoterTurnout < EffectiveVoterTurnout) + return Blockchain.StandbyCommittee.Select(p => (p, GetCandidate(snapshot, p)?.Votes ?? BigInteger.Zero)); + var candidates = GetCandidatesInternal(snapshot).ToDictionary(p => p.PublicKey, p => p.State); + if (candidates.Count(p => p.Value.Registered) < ProtocolSettings.Default.CommitteeMembersCount) + return Blockchain.StandbyCommittee.Select(p => + { + if (candidates.TryGetValue(p, out CandidateState candidate)) + return (p, candidate.Votes); + else + return (p, BigInteger.Zero); + }); + return candidates.OrderByDescending(p => p.Value.Votes).ThenBy(p => p.Key).Select(p => (p.Key, p.Value.Votes)).Take(ProtocolSettings.Default.CommitteeMembersCount); + } + [ContractMethod(1_00000000, CallFlags.AllowStates)] public ECPoint[] GetNextBlockValidators(StoreView snapshot) { From 4b753d2ebad5c5d2f3b6958fdb016dd5adeba24f Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 27 Aug 2020 10:50:03 +0800 Subject: [PATCH 11/60] specify variable name --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index b961bafc5d..0b91570be5 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -77,13 +77,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; - var keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); - var keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); - var enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator(); + StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); + StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); + IEnumerator<(StorageKey Key, StorageItem Value)> enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator(); if (!enumerator.MoveNext()) return neoHolderReward; var endRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); var startRewardPerNeo = BigInteger.Zero; - var keyMax = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue); + StorageKey keyMax = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue); enumerator = snapshot.Storages.FindRange(keyEnd, keyMax).GetEnumerator(); if (enumerator.MoveNext()) startRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); From eb9b7280eb44857cf3d16d77ae541e600634524a Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 28 Aug 2020 10:55:33 +0200 Subject: [PATCH 12/60] Remove double ToArray --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 0b91570be5..421dc98382 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -288,14 +288,14 @@ private CandidateState GetCandidate(StoreView snapshot, ECPoint pubkey) .ToArray(); } - private (ECPoint PublicKey, CandidateState State)[] GetCandidatesInternal(StoreView snapshot) + private IEnumerable<(ECPoint PublicKey, CandidateState State)> GetCandidatesInternal(StoreView snapshot) { byte[] prefix_key = CreateStorageKey(Prefix_Candidate).ToArray(); return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), p.Value.GetInteroperable() - )).ToArray(); + )); } [ContractMethod(1_00000000, CallFlags.AllowStates)] From ba0580069202ccd567a93e2a658900398289fb86 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Mon, 7 Sep 2020 19:41:46 +0800 Subject: [PATCH 13/60] fix ut --- .../SmartContract/Native/Tokens/NeoToken.cs | 15 ++- .../Native/Tokens/UT_NeoToken.cs | 100 +++++++++++------- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index a691ade74a..ec7262612c 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -46,7 +46,11 @@ public override BigInteger TotalSupply(StoreView snapshot) protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { - DistributeGas(engine, account, state); + var m = ProtocolSettings.Default.CommitteeMembersCount - ProtocolSettings.Default.ValidatorsCount; + if (state.BalanceHeight < engine.Snapshot.PersistingBlock.Index - 2 * m) + { + DistributeGas(engine, account, state); + } if (amount.IsZero) return; if (state.VoteTo != null) { @@ -86,8 +90,7 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v if (!enumerator.MoveNext()) return neoHolderReward; var endRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); var startRewardPerNeo = BigInteger.Zero; - StorageKey keyMax = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue); - enumerator = snapshot.Storages.FindRange(keyEnd, keyMax).GetEnumerator(); + enumerator = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Backward).GetEnumerator(); if (enumerator.MoveNext()) startRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); @@ -113,6 +116,7 @@ private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value break; } } + Console.WriteLine("value: " + value + " sum: " + sum); return value * sum * NeoHolderRewardRatio / 100 / TotalAmount; } @@ -167,11 +171,6 @@ protected override void PostPersist(ApplicationEngine engine) var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[cindex].PublicKey).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } - - // Set next validators - - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_NextValidators), () => new StorageItem()); - storage.Value = committee.Take(ProtocolSettings.Default.ValidatorsCount).OrderBy(p => p).ToArray().ToByteArray(); } [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 287c92f42e..90eefd5f72 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -14,6 +14,7 @@ using Neo.VM; using Neo.Wallets; using System; +using System.Collections.Generic; using System.Linq; using System.Numerics; using static Neo.SmartContract.Native.Tokens.NeoToken; @@ -500,7 +501,7 @@ public void TestCalculateBonus() VoteTo = Blockchain.StandbyCommittee[0] })); snapshot.Storages.Add(new KeyBuilder(-1, 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(100 * 100)); + NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 100).Should().Be(new BigInteger(50 * 100)); snapshot.Storages.Delete(key); } @@ -642,74 +643,75 @@ public void TestClaimGas() var snapshot = Blockchain.Singleton.GetSnapshot(); // Initialize block + snapshot.Storages.Add(CreateStorageKey(1), new StorageItem(new BigInteger(30000000))); for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) { ECPoint member = Blockchain.StandbyCommittee[i]; - var moreVotes = 0; - if (i < ProtocolSettings.Default.ValidatorsCount) - moreVotes += 10; snapshot.Storages.Add(new KeyBuilder(-1, 33).Add(member), new StorageItem(new CandidateState() { Registered = true, - Votes = 100 * 10000 + moreVotes + Votes = 200 * 10000 - i * 100 })); } var item = snapshot.Storages.GetAndChange(new KeyBuilder(-1, 1), () => new StorageItem()); item.Value = ((BigInteger)2100 * 10000L).ToByteArray(); snapshot.PersistingBlock = new Block { Index = 0 }; - Check_OnPersist(snapshot).Should().BeTrue(); + Check_PostPersist(snapshot).Should().BeTrue(); - for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) - { - ECPoint member = Blockchain.StandbyCommittee[i]; - StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1)); - if (i < ProtocolSettings.Default.ValidatorsCount) - new BigInteger(storageItem.Value).Should().Be(303568); - else - new BigInteger(storageItem.Value).Should().Be(151785); - } + var committeeA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[0]; + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + + var committeeB = Blockchain.StandbyCommittee[0]; + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1)); + new BigInteger(storageItem.Value).Should().Be(25000000000); // Next block snapshot.PersistingBlock = new Block { Index = 1 }; - Check_OnPersist(snapshot).Should().BeTrue(); - for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) - { - ECPoint member = Blockchain.StandbyCommittee[i]; - StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1 - 1)); - if (i < ProtocolSettings.Default.ValidatorsCount) - new BigInteger(storageItem.Value).Should().Be(303568 * 2); - else - new BigInteger(storageItem.Value).Should().Be(151785 * 2); - } + Check_PostPersist(snapshot).Should().BeTrue(); + + committeeA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[1]; + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + + committeeB = Blockchain.StandbyCommittee[1]; + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1 - 1)); + new BigInteger(storageItem.Value).Should().Be(25001250062); // Next block snapshot.PersistingBlock = new Block { Index = 2 }; - Check_OnPersist(snapshot).Should().BeTrue(); - for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++) - { - ECPoint member = Blockchain.StandbyCommittee[i]; - StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(member).AddBigEndian(uint.MaxValue - 1 - 2)); - if (i < ProtocolSettings.Default.ValidatorsCount) - new BigInteger(storageItem.Value).Should().Be(303568 * 3); - else - new BigInteger(storageItem.Value).Should().Be(151785 * 3); - } + Check_PostPersist(snapshot).Should().BeTrue(); + + committeeA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[2]; + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + + committeeB = Blockchain.StandbyCommittee[2]; + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1 - 2)); + new BigInteger(storageItem.Value).Should().Be(25002500250); + // Claim GAS - var account = Contract.CreateSignatureContract(Blockchain.StandbyCommittee[0]).ScriptHash; + snapshot.PersistingBlock = new Block { Index = 2 + 28 }; + + Check_PostPersist(snapshot).Should().BeTrue(); + + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1 - 2 - 28)); + new BigInteger(storageItem.Value).Should().Be(25002500250 * 2); + + var account = Contract.CreateSignatureContract(committeeB).ScriptHash; snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState { BalanceHeight = 1, - Balance = 100, - VoteTo = Blockchain.StandbyCommittee[0] + Balance = 200 * 10000 - 2 * 100, + VoteTo = committeeB })); - BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2); - value.Should().Be(3085); + NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(1999800); + BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1); + value.Should().Be(1999800 * 25002500250 / 100000000L + (1999800L * 10 * 5 * 30 / 100)); } [TestMethod] @@ -803,6 +805,24 @@ internal static bool Check_OnPersist(StoreView snapshot) return engine.Execute() == VMState.HALT; } + internal static bool Check_PostPersist(StoreView snapshot) + { + ECPoint[] committees = NativeContract.NEO.GetCommittee(snapshot); + UInt160 committeesMultisign = Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); + var engine = ApplicationEngine.Create(TriggerType.System, + new Nep5NativeContractExtensions.ManualWitness(committeesMultisign), snapshot); + + engine.LoadScript(NativeContract.NEO.Script); + + var script = new ScriptBuilder(); + script.EmitPush(0); + script.Emit(OpCode.PACK); + script.EmitPush("postPersist"); + engine.LoadScript(script.ToArray()); + + return engine.Execute() == VMState.HALT; + } + internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); From 5e4abe78509ba63d2c7adc9d09e780d38bc3109a Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 8 Sep 2020 14:06:18 +0800 Subject: [PATCH 14/60] remove --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index ec7262612c..fc84208f26 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -48,9 +48,8 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco { var m = ProtocolSettings.Default.CommitteeMembersCount - ProtocolSettings.Default.ValidatorsCount; if (state.BalanceHeight < engine.Snapshot.PersistingBlock.Index - 2 * m) - { DistributeGas(engine, account, state); - } + if (amount.IsZero) return; if (state.VoteTo != null) { @@ -116,7 +115,6 @@ private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value break; } } - Console.WriteLine("value: " + value + " sum: " + sum); return value * sum * NeoHolderRewardRatio / 100 / TotalAmount; } From 77fe460ffa57f84c63f712280eff08239a49326e Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 11 Sep 2020 16:50:00 +0800 Subject: [PATCH 15/60] fix --- .../SmartContract/Native/Tokens/NeoToken.cs | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index c9f28675b6..a330c843bd 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -163,15 +163,17 @@ protected override void PostPersist(ApplicationEngine engine) var m = ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount; var cindex = engine.Snapshot.PersistingBlock.Index % m % ProtocolSettings.Default.CommitteeMembersCount; - var committeeVotes = GetCommitteeVotes(engine.Snapshot).ToArray(); - if (committeeVotes[cindex].Votes > 0) + var votee = committee[cindex]; + StorageItem storage_validator = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(votee)); + CandidateState state_validator = storage_validator.GetInteroperable(); + if (state_validator.Votes > 0) { - BigInteger voterSumRewardPerNEO = gasPerBlock * 100000000L / committeeVotes[cindex].Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L - var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[cindex].PublicKey); + BigInteger voterSumRewardPerNEO = gasPerBlock * 100000000L / state_validator.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee); var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(committeeVotes[cindex].PublicKey).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } @@ -345,24 +347,6 @@ private IEnumerable ComputeCommitteeMembers(StoreView snapshot) return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } - private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetCommitteeVotes(StoreView snapshot) - { - decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; - decimal VoterTurnout = votersCount / (decimal)TotalAmount; - if (VoterTurnout < EffectiveVoterTurnout) - return Blockchain.StandbyCommittee.Select(p => (p, GetCandidate(snapshot, p)?.Votes ?? BigInteger.Zero)); - var candidates = GetCandidatesInternal(snapshot).ToDictionary(p => p.PublicKey, p => p.State); - if (candidates.Count(p => p.Value.Registered) < ProtocolSettings.Default.CommitteeMembersCount) - return Blockchain.StandbyCommittee.Select(p => - { - if (candidates.TryGetValue(p, out CandidateState candidate)) - return (p, candidate.Votes); - else - return (p, BigInteger.Zero); - }); - return candidates.OrderByDescending(p => p.Value.Votes).ThenBy(p => p.Key).Select(p => (p.Key, p.Value.Votes)).Take(ProtocolSettings.Default.CommitteeMembersCount); - } - [ContractMethod(1_00000000, CallFlags.AllowStates)] public ECPoint[] GetNextBlockValidators(StoreView snapshot) { From 2a806ef53d327e9d6111d88f5722144f35eb2760 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 11 Sep 2020 18:50:11 +0800 Subject: [PATCH 16/60] fix --- .../SmartContract/Native/Tokens/NeoToken.cs | 10 ++--- .../Native/Tokens/UT_NeoToken.cs | 42 +++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index a330c843bd..62b336f72c 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -47,8 +47,7 @@ public override BigInteger TotalSupply(StoreView snapshot) protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { var m = ProtocolSettings.Default.CommitteeMembersCount - ProtocolSettings.Default.ValidatorsCount; - if (state.BalanceHeight < engine.Snapshot.PersistingBlock.Index - 2 * m) - DistributeGas(engine, account, state); + DistributeGas(engine, account, state); if (amount.IsZero) return; if (state.VoteTo != null) @@ -164,11 +163,10 @@ protected override void PostPersist(ApplicationEngine engine) var m = ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount; var cindex = engine.Snapshot.PersistingBlock.Index % m % ProtocolSettings.Default.CommitteeMembersCount; var votee = committee[cindex]; - StorageItem storage_validator = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(votee)); - CandidateState state_validator = storage_validator.GetInteroperable(); - if (state_validator.Votes > 0) + CandidateState candidate = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(votee))?.GetInteroperable(); + if (candidate?.Votes > 0) { - BigInteger voterSumRewardPerNEO = gasPerBlock * 100000000L / state_validator.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + BigInteger voterSumRewardPerNEO = gasPerBlock * 100000000L / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee); var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 8bb2d922c1..f5f13a65a9 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -669,7 +669,7 @@ public void TestClaimGas() snapshot.Storages.Add(new KeyBuilder(-1, 33).Add(member), new StorageItem(new CandidateState() { Registered = true, - Votes = 200 * 10000 - i * 100 + Votes = 200 * 10000 })); } var item = snapshot.Storages.GetAndChange(new KeyBuilder(-1, 1), () => new StorageItem()); @@ -678,36 +678,36 @@ public void TestClaimGas() snapshot.PersistingBlock = new Block { Index = 0 }; Check_PostPersist(snapshot).Should().BeTrue(); - var committeeA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[0]; - NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + var committee = NativeContract.NEO.GetCommittee(snapshot); + var accountA = committee[0]; + var accountB = committee[ProtocolSettings.Default.CommitteeMembersCount - 1]; + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(accountA).ScriptHash).Should().Be(0); - var committeeB = Blockchain.StandbyCommittee[0]; - StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1)); + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountA).AddBigEndian(uint.MaxValue - 1)); new BigInteger(storageItem.Value).Should().Be(25000000000); + snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull(); + // Next block snapshot.PersistingBlock = new Block { Index = 1 }; Check_PostPersist(snapshot).Should().BeTrue(); - committeeA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[1]; - NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0); - committeeB = Blockchain.StandbyCommittee[1]; - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1 - 1)); - new BigInteger(storageItem.Value).Should().Be(25001250062); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(uint.MaxValue - 1 - 1)); + new BigInteger(storageItem.Value).Should().Be(25000000000); // Next block snapshot.PersistingBlock = new Block { Index = 2 }; Check_PostPersist(snapshot).Should().BeTrue(); - committeeA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[2]; - NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); + accountA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[2]; + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); - committeeB = Blockchain.StandbyCommittee[2]; - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1 - 2)); - new BigInteger(storageItem.Value).Should().Be(25002500250); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(uint.MaxValue - 1 - 2)); + new BigInteger(storageItem.Value).Should().Be(25000000000); // Claim GAS @@ -716,20 +716,20 @@ public void TestClaimGas() Check_PostPersist(snapshot).Should().BeTrue(); - NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committeeA).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committeeB).AddBigEndian(uint.MaxValue - 1 - 2 - 28)); - new BigInteger(storageItem.Value).Should().Be(25002500250 * 2); + NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(uint.MaxValue - 1 - 2 - 28)); + new BigInteger(storageItem.Value).Should().Be(25000000000 * 2); - var account = Contract.CreateSignatureContract(committeeB).ScriptHash; + var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState { BalanceHeight = 1, Balance = 200 * 10000 - 2 * 100, - VoteTo = committeeB + VoteTo = committee[2] })); NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(1999800); BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1); - value.Should().Be(1999800 * 25002500250 / 100000000L + (1999800L * 10 * 5 * 30 / 100)); + value.Should().Be(1999800 * 25000000000 / 100000000L + (1999800L * 10 * 5 * 30 / 100)); } [TestMethod] From 67aafdc515d5eb58d757c8676b4b456d40fe7f8c Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 11 Sep 2020 19:00:25 +0800 Subject: [PATCH 17/60] remove useless code --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 62b336f72c..248336fa56 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -286,29 +286,15 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) return true; } - private CandidateState GetCandidate(StoreView snapshot, ECPoint pubkey) - { - StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - return snapshot.Storages.TryGet(key)?.GetInteroperable(); - } - [ContractMethod(1_00000000, CallFlags.AllowStates)] public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(StoreView snapshot) - { - return GetCandidatesInternal(snapshot) - .Where(p => p.State.Registered) - .Select(p => (p.PublicKey, p.State.Votes)) - .ToArray(); - } - - private IEnumerable<(ECPoint PublicKey, CandidateState State)> GetCandidatesInternal(StoreView snapshot) { byte[] prefix_key = CreateStorageKey(Prefix_Candidate).ToArray(); return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), p.Value.GetInteroperable() - )); + )).Where(p => p.Item2.Registered).Select(p => (p.Item1, p.Item2.Votes)).ToArray(); } [ContractMethod(1_00000000, CallFlags.AllowStates)] From 675fe7a80f38b1c556914c5df53966cf254bfe55 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 11 Sep 2020 19:02:00 +0800 Subject: [PATCH 18/60] optimize --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 248336fa56..54ce4ebd78 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -46,9 +46,7 @@ public override BigInteger TotalSupply(StoreView snapshot) protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { - var m = ProtocolSettings.Default.CommitteeMembersCount - ProtocolSettings.Default.ValidatorsCount; DistributeGas(engine, account, state); - if (amount.IsZero) return; if (state.VoteTo != null) { From 6ffc60179c76b4dcda9004a19c530e16a7954896 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Mon, 14 Sep 2020 11:39:10 +0800 Subject: [PATCH 19/60] fix --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 41fb3a5954..6fdbef1c92 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -261,6 +261,7 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) else item.Add(-state_account.Balance); } + DistributeGas(engine, account, state_account); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); @@ -269,7 +270,6 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) state_validator.Votes -= state_account.Balance; if (!state_validator.Registered && state_validator.Votes.IsZero) { - DistributeGas(engine, account, state_account); UInt160 voteeAddr = Contract.CreateSignatureContract(state_account.VoteTo).ScriptHash; foreach (var (rewardKey, _) in engine.Snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteeAddr).ToArray())) engine.Snapshot.Storages.Delete(rewardKey); From 8b0682454e839f3cc59ddd820f1d19e13a02eccc Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 15 Sep 2020 17:05:29 +0800 Subject: [PATCH 20/60] format --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index d3b103f1c4..9adf041664 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -110,7 +110,7 @@ private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value } private void CheckCandidate(StoreView snapshot, StorageKey key, CandidateState candidate) - { + { if (!candidate.Registered && candidate.Votes.IsZero) { ECPoint pubKey = ECPoint.FromBytes(key.Key.Skip(1).ToArray(), ECCurve.Secp256r1); From c49a809b414a482d2ea413f429e932cc6e3973b1 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Wed, 16 Sep 2020 16:30:31 +0800 Subject: [PATCH 21/60] Add using to dispose enumerators --- .../SmartContract/Native/Tokens/NeoToken.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 9adf041664..a344fcac80 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -74,16 +74,21 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; + BigInteger startRewardPerNeo, endRewardPerNeo; StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); - IEnumerator<(StorageKey Key, StorageItem Value)> enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator(); - if (!enumerator.MoveNext()) return neoHolderReward; - var endRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); - var startRewardPerNeo = BigInteger.Zero; - enumerator = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Backward).GetEnumerator(); - if (enumerator.MoveNext()) - startRewardPerNeo = new BigInteger(enumerator.Current.Value.Value); - + using (var enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator()) + { + if (!enumerator.MoveNext()) return neoHolderReward; + endRewardPerNeo = enumerator.Current.Value; + } + using (var enumerator = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Backward).GetEnumerator()) + { + if (enumerator.MoveNext()) + startRewardPerNeo = enumerator.Current.Value; + else + startRewardPerNeo = BigInteger.Zero; + } return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } From bf00ca1ec02b9ef12f306c4044951e90cb431fb9 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Thu, 17 Sep 2020 15:44:06 +0800 Subject: [PATCH 22/60] Update NeoToken.cs --- .../SmartContract/Native/Tokens/NeoToken.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index a344fcac80..ebf59caee5 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -74,21 +74,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; - BigInteger startRewardPerNeo, endRewardPerNeo; StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); - using (var enumerator = snapshot.Storages.FindRange(keyStart, keyEnd).GetEnumerator()) - { - if (!enumerator.MoveNext()) return neoHolderReward; - endRewardPerNeo = enumerator.Current.Value; - } - using (var enumerator = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Backward).GetEnumerator()) - { - if (enumerator.MoveNext()) - startRewardPerNeo = enumerator.Current.Value; - else - startRewardPerNeo = BigInteger.Zero; - } + (_, var item) = snapshot.Storages.FindRange(keyStart, keyEnd).FirstOrDefault(); + if (item is null) return neoHolderReward; + BigInteger endRewardPerNeo = item; + (_, item) = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Backward).FirstOrDefault(); + BigInteger startRewardPerNeo = item ?? BigInteger.Zero; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } From fed12df9479eddb10c67969665efbd755d5d0abb Mon Sep 17 00:00:00 2001 From: erikzhang Date: Thu, 17 Sep 2020 16:04:49 +0800 Subject: [PATCH 23/60] Update NeoToken.cs --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index ebf59caee5..bdb2aaffdb 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -53,7 +53,7 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); CandidateState candidate = engine.Snapshot.Storages.GetAndChange(key).GetInteroperable(); candidate.Votes += amount; - CheckCandidate(engine.Snapshot, key, candidate); + CheckCandidate(engine.Snapshot, state.VoteTo, candidate); } private void DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) @@ -106,15 +106,14 @@ private BigInteger CalculateNeoHolderReward(StoreView snapshot, BigInteger value return value * sum * NeoHolderRewardRatio / 100 / TotalAmount; } - private void CheckCandidate(StoreView snapshot, StorageKey key, CandidateState candidate) + private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState candidate) { if (!candidate.Registered && candidate.Votes.IsZero) { - ECPoint pubKey = ECPoint.FromBytes(key.Key.Skip(1).ToArray(), ECCurve.Secp256r1); - UInt160 voteeAddr = Contract.CreateSignatureContract(pubKey).ScriptHash; + UInt160 voteeAddr = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); foreach (var (rewardKey, _) in snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteeAddr).ToArray())) snapshot.Storages.Delete(rewardKey); - snapshot.Storages.Delete(key); + snapshot.Storages.Delete(CreateStorageKey(Prefix_Candidate).Add(pubkey)); } } @@ -237,7 +236,7 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) StorageItem item = engine.Snapshot.Storages.GetAndChange(key); CandidateState state = item.GetInteroperable(); state.Registered = false; - CheckCandidate(engine.Snapshot, key, state); + CheckCandidate(engine.Snapshot, pubkey, state); return true; } @@ -269,7 +268,7 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; - CheckCandidate(engine.Snapshot, key, state_validator); + CheckCandidate(engine.Snapshot, state_account.VoteTo, state_validator); } state_account.VoteTo = voteTo; if (validator_new != null) From 87e1d9d5eecd389eccb025014b79ab8ad558d250 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 17 Sep 2020 18:42:04 +0800 Subject: [PATCH 24/60] fix --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index bdb2aaffdb..a58433fe00 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -110,8 +110,7 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c { if (!candidate.Registered && candidate.Votes.IsZero) { - UInt160 voteeAddr = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); - foreach (var (rewardKey, _) in snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteeAddr).ToArray())) + foreach (var (rewardKey, _) in snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray())) snapshot.Storages.Delete(rewardKey); snapshot.Storages.Delete(CreateStorageKey(Prefix_Candidate).Add(pubkey)); } From 057099714925cadcd68bbd5b13050ef4a5bd0544 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 18 Sep 2020 17:27:51 +0800 Subject: [PATCH 25/60] fix CalculateBonus --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index a58433fe00..78c1dbbb8c 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -76,11 +76,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); - (_, var item) = snapshot.Storages.FindRange(keyStart, keyEnd).FirstOrDefault(); + (var key, var item) = snapshot.Storages.FindRange(keyStart, keyEnd).FirstOrDefault(); if (item is null) return neoHolderReward; BigInteger endRewardPerNeo = item; - (_, item) = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Backward).FirstOrDefault(); - BigInteger startRewardPerNeo = item ?? BigInteger.Zero; + (key, item) = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Forward).FirstOrDefault(); + BigInteger startRewardPerNeo = BigInteger.Zero; + if (key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) + startRewardPerNeo = item; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } From 4a1274842d62b06a1e45a20578f90d783787cc5a Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 18 Sep 2020 18:14:54 +0800 Subject: [PATCH 26/60] Usng asending order --- .../SmartContract/Native/Tokens/NeoToken.cs | 19 +++++++++++-------- .../Native/Tokens/UT_NeoToken.cs | 8 ++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 78c1dbbb8c..9560cff447 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -2,6 +2,7 @@ using Neo.Cryptography.ECC; using Neo.IO; +using Neo.IO.Caching; using Neo.Ledger; using Neo.Persistence; using Neo.VM; @@ -74,15 +75,17 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; - StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - end); - StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(uint.MaxValue - start); - (var key, var item) = snapshot.Storages.FindRange(keyStart, keyEnd).FirstOrDefault(); - if (item is null) return neoHolderReward; - BigInteger endRewardPerNeo = item; - (key, item) = snapshot.Storages.Seek(keyEnd.ToArray(), IO.Caching.SeekDirection.Forward).FirstOrDefault(); + StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start); + (var key, var item) = snapshot.Storages.Seek(keyStart.ToArray(), SeekDirection.Backward).FirstOrDefault(); BigInteger startRewardPerNeo = BigInteger.Zero; - if (key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) + if (key != null && key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) startRewardPerNeo = item; + + StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end); + (key, item) = snapshot.Storages.Seek(keyEnd.ToArray(), SeekDirection.Backward).FirstOrDefault(); + BigInteger endRewardPerNeo = BigInteger.Zero; + if (key != null && key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) + endRewardPerNeo = item; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } @@ -173,7 +176,7 @@ protected override void PostPersist(ApplicationEngine engine) var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee).AddBigEndian(uint.MaxValue - engine.Snapshot.PersistingBlock.Index - 1); + var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee).AddBigEndian(engine.Snapshot.PersistingBlock.Index); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index f5f13a65a9..cd09f697b6 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -683,7 +683,7 @@ 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(-1, 23).Add(accountA).AddBigEndian(uint.MaxValue - 1)); + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountA).AddBigEndian(0)); new BigInteger(storageItem.Value).Should().Be(25000000000); snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull(); @@ -695,7 +695,7 @@ public void TestClaimGas() NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(uint.MaxValue - 1 - 1)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(1)); new BigInteger(storageItem.Value).Should().Be(25000000000); // Next block @@ -706,7 +706,7 @@ public void TestClaimGas() 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(-1, 23).Add(committee[2]).AddBigEndian(uint.MaxValue - 1 - 2)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2)); new BigInteger(storageItem.Value).Should().Be(25000000000); @@ -717,7 +717,7 @@ public void TestClaimGas() Check_PostPersist(snapshot).Should().BeTrue(); NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(uint.MaxValue - 1 - 2 - 28)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2 + 28)); new BigInteger(storageItem.Value).Should().Be(25000000000 * 2); var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; From 321f5f8db744cc1f4dadabd0019827f0292f1f77 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Tue, 22 Sep 2020 09:53:52 +0800 Subject: [PATCH 27/60] Update NeoToken.cs --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 9560cff447..906ef167cb 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -76,7 +76,7 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v if (vote is null) return neoHolderReward; StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start); - (var key, var item) = snapshot.Storages.Seek(keyStart.ToArray(), SeekDirection.Backward).FirstOrDefault(); + var (key, item) = snapshot.Storages.Seek(keyStart.ToArray(), SeekDirection.Backward).FirstOrDefault(); BigInteger startRewardPerNeo = BigInteger.Zero; if (key != null && key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) startRewardPerNeo = item; From 57b6e324136f6f56ca0894c29d2aaa978b94a55d Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 22 Sep 2020 11:13:19 +0800 Subject: [PATCH 28/60] fix --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 5 +++-- .../neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 906ef167cb..8a92596547 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -1,5 +1,6 @@ #pragma warning disable IDE0051 +using Microsoft.EntityFrameworkCore.Internal; using Neo.Cryptography.ECC; using Neo.IO; using Neo.IO.Caching; @@ -78,13 +79,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start); var (key, item) = snapshot.Storages.Seek(keyStart.ToArray(), SeekDirection.Backward).FirstOrDefault(); BigInteger startRewardPerNeo = BigInteger.Zero; - if (key != null && key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) + if (key != null && key.Id == Id && key.Key.Take(1 + vote.Size).SequenceEqual(keyStart.Key.Take(1 + vote.Size))) startRewardPerNeo = item; StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end); (key, item) = snapshot.Storages.Seek(keyEnd.ToArray(), SeekDirection.Backward).FirstOrDefault(); BigInteger endRewardPerNeo = BigInteger.Zero; - if (key != null && key.Id == Id && key.Key[0] == Prefix_VoterRewardPerCommittee) + if (key != null && key.Id == Id && key.Key.Take(1 + vote.Size).SequenceEqual(keyEnd.Key.Take(1 + vote.Size))) endRewardPerNeo = item; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 0878f8433f..95a0fe94d2 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -722,13 +722,13 @@ public void TestClaimGas() var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState { - BalanceHeight = 1, + BalanceHeight = 2, Balance = 200 * 10000 - 2 * 100, VoteTo = committee[2] })); NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(1999800); BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1); - value.Should().Be(1999800 * 25000000000 / 100000000L + (1999800L * 10 * 5 * 30 / 100)); + value.Should().Be(1999800 * 25000000000 / 100000000L + (1999800L * 10 * 5 * 29 / 100)); } [TestMethod] From 9af4bb3df5812233728ae8722b94d1a3ddb8c616 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 24 Sep 2020 20:42:28 +0800 Subject: [PATCH 29/60] optimize findrange --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 8a92596547..d5b1633df3 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -76,17 +76,15 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; + StorageKey border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote); StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start); - var (key, item) = snapshot.Storages.Seek(keyStart.ToArray(), SeekDirection.Backward).FirstOrDefault(); - BigInteger startRewardPerNeo = BigInteger.Zero; - if (key != null && key.Id == Id && key.Key.Take(1 + vote.Size).SequenceEqual(keyStart.Key.Take(1 + vote.Size))) - startRewardPerNeo = item; + (_, var item) = snapshot.Storages.FindRange(border, keyStart, SeekDirection.Backward).FirstOrDefault(); + BigInteger startRewardPerNeo = item ?? BigInteger.Zero; StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end); - (key, item) = snapshot.Storages.Seek(keyEnd.ToArray(), SeekDirection.Backward).FirstOrDefault(); - BigInteger endRewardPerNeo = BigInteger.Zero; - if (key != null && key.Id == Id && key.Key.Take(1 + vote.Size).SequenceEqual(keyEnd.Key.Take(1 + vote.Size))) - endRewardPerNeo = item; + (_, item) = snapshot.Storages.FindRange(border, keyEnd, SeekDirection.Backward).FirstOrDefault(); + BigInteger endRewardPerNeo = item ?? BigInteger.Zero; + return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } From 40e73def9129c81fda8563231da5b64104b7bdb3 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 24 Sep 2020 20:44:36 +0800 Subject: [PATCH 30/60] format --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index d5b1633df3..f96fc2d822 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -83,7 +83,7 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end); (_, item) = snapshot.Storages.FindRange(border, keyEnd, SeekDirection.Backward).FirstOrDefault(); - BigInteger endRewardPerNeo = item ?? BigInteger.Zero; + BigInteger endRewardPerNeo = item ?? BigInteger.Zero; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; } From 53950b45b7fbf4b2d65ce2e16b886e5b9e105553 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 25 Sep 2020 16:37:07 +0800 Subject: [PATCH 31/60] optimize --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index f96fc2d822..062ad47716 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -76,13 +76,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; - StorageKey border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote); + var border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).ToArray(); StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start); - (_, var item) = snapshot.Storages.FindRange(border, keyStart, SeekDirection.Backward).FirstOrDefault(); + (_, var item) = snapshot.Storages.FindRange(keyStart.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); BigInteger startRewardPerNeo = item ?? BigInteger.Zero; StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end); - (_, item) = snapshot.Storages.FindRange(border, keyEnd, SeekDirection.Backward).FirstOrDefault(); + (_, item) = snapshot.Storages.FindRange(keyEnd.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); BigInteger endRewardPerNeo = item ?? BigInteger.Zero; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; From 849be7c5d8dbd55a7fc9989f9f4ffe8c14ec91ed Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 25 Sep 2020 16:59:22 +0800 Subject: [PATCH 32/60] Update NeoToken.cs --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 062ad47716..a1083033ec 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -1,6 +1,5 @@ #pragma warning disable IDE0051 -using Microsoft.EntityFrameworkCore.Internal; using Neo.Cryptography.ECC; using Neo.IO; using Neo.IO.Caching; @@ -76,13 +75,13 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; - var border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).ToArray(); - StorageKey keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start); - (_, var item) = snapshot.Storages.FindRange(keyStart.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); + 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(); BigInteger startRewardPerNeo = item ?? BigInteger.Zero; - StorageKey keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end); - (_, item) = snapshot.Storages.FindRange(keyEnd.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); + byte[] keyEnd = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(end).ToArray(); + (_, item) = snapshot.Storages.FindRange(keyEnd, border, SeekDirection.Backward).FirstOrDefault(); BigInteger endRewardPerNeo = item ?? BigInteger.Zero; return neoHolderReward + value * (endRewardPerNeo - startRewardPerNeo) / 100000000L; From 94caa538e90333f5d3a66585ecd1c8f2562816e7 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sun, 27 Sep 2020 14:17:11 +0800 Subject: [PATCH 33/60] fix --- .../SmartContract/Native/Tokens/NeoToken.cs | 18 +++++++++--------- .../SmartContract/Native/Tokens/UT_NeoToken.cs | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index a1083033ec..a109a24e0f 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -119,7 +119,7 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c } } - private bool ShouldRefreshCommittee(uint height) => height % (ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount) == 0; + private bool ShouldRefreshCommittee(uint height) => height % ProtocolSettings.Default.CommitteeMembersCount == 0; internal override void Initialize(ApplicationEngine engine) { @@ -154,7 +154,9 @@ protected override void PostPersist(ApplicationEngine engine) // Distribute GAS for committee - int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)ProtocolSettings.Default.CommitteeMembersCount); + int m = ProtocolSettings.Default.CommitteeMembersCount; + int n = ProtocolSettings.Default.ValidatorsCount; + int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)m); var gasPerBlock = GetGasPerBlock(engine.Snapshot); var committee = GetCommittee(engine.Snapshot); var pubkey = committee[index]; @@ -163,18 +165,16 @@ protected override void PostPersist(ApplicationEngine engine) // Record the cumulative reward of the voters of committee - var m = ProtocolSettings.Default.CommitteeMembersCount + ProtocolSettings.Default.ValidatorsCount; - var cindex = engine.Snapshot.PersistingBlock.Index % m % ProtocolSettings.Default.CommitteeMembersCount; - var votee = committee[cindex]; - CandidateState candidate = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(votee))?.GetInteroperable(); + var factor = index < n ? 2 : 1; + CandidateState candidate = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubkey))?.GetInteroperable(); if (candidate?.Votes > 0) { - BigInteger voterSumRewardPerNEO = gasPerBlock * 100000000L / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L - var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee); + BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey); var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(votee).AddBigEndian(engine.Snapshot.PersistingBlock.Index); + var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 95a0fe94d2..64d654c98e 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -683,7 +683,7 @@ public void TestClaimGas() NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(accountA).ScriptHash).Should().Be(0); StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountA).AddBigEndian(0)); - new BigInteger(storageItem.Value).Should().Be(25000000000); + new BigInteger(storageItem.Value).Should().Be(31875000000); snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull(); @@ -695,7 +695,7 @@ public void TestClaimGas() NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0); storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(1)); - new BigInteger(storageItem.Value).Should().Be(25000000000); + new BigInteger(storageItem.Value).Should().Be(31875000000); // Next block @@ -706,18 +706,18 @@ public void TestClaimGas() NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2)); - new BigInteger(storageItem.Value).Should().Be(25000000000); + new BigInteger(storageItem.Value).Should().Be(31875000000); // Claim GAS - snapshot.PersistingBlock = new Block { Index = 2 + 28 }; + snapshot.PersistingBlock = new Block { Index = 2 + 21 }; Check_PostPersist(snapshot).Should().BeTrue(); NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2 + 28)); - new BigInteger(storageItem.Value).Should().Be(25000000000 * 2); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2 + 21)); + new BigInteger(storageItem.Value).Should().Be(31875000000 * 2); var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState @@ -728,7 +728,7 @@ public void TestClaimGas() })); NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(1999800); BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1); - value.Should().Be(1999800 * 25000000000 / 100000000L + (1999800L * 10 * 5 * 29 / 100)); + value.Should().Be(1999800 * 31875000000 / 100000000L + (1999800L * 10 * 5 * 29 / 100)); } [TestMethod] From c95ff95e983a789dca94a8dacadfdfc1d0d0c9c3 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Sun, 27 Sep 2020 14:20:00 +0800 Subject: [PATCH 34/60] format --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index a109a24e0f..288d4bc9ae 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -169,7 +169,7 @@ protected override void PostPersist(ApplicationEngine engine) CandidateState candidate = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubkey))?.GetInteroperable(); if (candidate?.Votes > 0) { - BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey); var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); if (enumerator.MoveNext()) From d811ce8f92b14ed2b3763d5c4037681dac948be9 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sun, 27 Sep 2020 19:49:50 +0800 Subject: [PATCH 35/60] Use GetCommitteeFromCache --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 288d4bc9ae..0015e86753 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -158,8 +158,7 @@ protected override void PostPersist(ApplicationEngine engine) int n = ProtocolSettings.Default.ValidatorsCount; int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)m); var gasPerBlock = GetGasPerBlock(engine.Snapshot); - var committee = GetCommittee(engine.Snapshot); - var pubkey = committee[index]; + var pubkey = GetCommitteeFromCache(engine.Snapshot).ElementAt(index); var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); From f5f92595cdbbd2e4da8687ca3d1265abd2ada237 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sun, 27 Sep 2020 20:15:35 +0800 Subject: [PATCH 36/60] Ensure registered --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 0015e86753..e2769588de 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -166,7 +166,8 @@ protected override void PostPersist(ApplicationEngine engine) var factor = index < n ? 2 : 1; CandidateState candidate = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubkey))?.GetInteroperable(); - if (candidate?.Votes > 0) + if (candidate is null) return; + if (candidate.Registered && candidate.Votes > 0) { BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey); From 36ec672f5521692486e0290a6d70c32c14d88eae Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Mon, 28 Sep 2020 01:01:22 +0800 Subject: [PATCH 37/60] fix PostPersist --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 9 ++++----- .../SmartContract/Native/Tokens/UT_NeoToken.cs | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index e2769588de..e589a875c6 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -170,11 +170,10 @@ protected override void PostPersist(ApplicationEngine engine) if (candidate.Registered && candidate.Votes > 0) { BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L - var voterRewardKeyPrefix = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey); - var enumerator = engine.Snapshot.Storages.Find(voterRewardKeyPrefix.ToArray()).GetEnumerator(); - if (enumerator.MoveNext()) - voterSumRewardPerNEO += new BigInteger(enumerator.Current.Value.Value); - var voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index); + StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index); + byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); + (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); + voterSumRewardPerNEO += (item ?? BigInteger.Zero); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); } } diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 64d654c98e..de96674c71 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -418,7 +418,7 @@ public void Check_CommitteeBonus() engine.Execute(); engine.State.Should().Be(VM.VMState.HALT); - var committee = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray(); + var committee = Blockchain.StandbyCommittee; NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[0]).ScriptHash.ToArray()).Should().Be(25000000); NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash.ToArray()).Should().Be(25000000); NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash.ToArray()).Should().Be(0); @@ -677,7 +677,7 @@ public void TestClaimGas() snapshot.PersistingBlock = new Block { Index = 0 }; Check_PostPersist(snapshot).Should().BeTrue(); - var committee = NativeContract.NEO.GetCommittee(snapshot); + var committee = Blockchain.StandbyCommittee; var accountA = committee[0]; var accountB = committee[ProtocolSettings.Default.CommitteeMembersCount - 1]; NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(accountA).ScriptHash).Should().Be(0); From 251d633b765ffee7b460baa5ee1548a74c30aae4 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 28 Sep 2020 08:16:19 +0800 Subject: [PATCH 38/60] Update NeoToken.cs --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index e589a875c6..f5f968c95f 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -174,7 +174,7 @@ protected override void PostPersist(ApplicationEngine engine) byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); voterSumRewardPerNEO += (item ?? BigInteger.Zero); - engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem() { Value = voterSumRewardPerNEO.ToByteArray() }); + engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); } } From 268bc86ce6040d61288f781bb9f25ec7da71ddaa Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Mon, 28 Sep 2020 18:07:32 +0800 Subject: [PATCH 39/60] cache committee votes --- .../SmartContract/Native/Tokens/NeoToken.cs | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index e589a875c6..dae36ac9b2 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -9,6 +9,7 @@ using Neo.VM.Types; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Numerics; using Array = Neo.VM.Types.Array; @@ -123,7 +124,7 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c internal override void Initialize(ApplicationEngine engine) { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Committee), new StorageItem(Blockchain.StandbyCommittee.ToByteArray())); + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Committee), new StorageItem(Blockchain.StandbyCommittee.Select(p => new CommitteeState { PublicKey = p }).ToArray().ToByteArray())); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(new byte[0])); // Initialize economic parameters @@ -158,18 +159,17 @@ protected override void PostPersist(ApplicationEngine engine) int n = ProtocolSettings.Default.ValidatorsCount; int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)m); var gasPerBlock = GetGasPerBlock(engine.Snapshot); - var pubkey = GetCommitteeFromCache(engine.Snapshot).ElementAt(index); + var committeeState = GetCommitteeFromCache(engine.Snapshot).ElementAt(index); + var pubkey = committeeState.PublicKey; var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); // Record the cumulative reward of the voters of committee var factor = index < n ? 2 : 1; - CandidateState candidate = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubkey))?.GetInteroperable(); - if (candidate is null) return; - if (candidate.Registered && candidate.Votes > 0) + if (committeeState.Votes > 0) { - BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / candidate.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / committeeState.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index); byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); @@ -293,7 +293,7 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) [ContractMethod(1_00000000, CallFlags.AllowStates)] public ECPoint[] GetCommittee(StoreView snapshot) { - return GetCommitteeFromCache(snapshot).OrderBy(p => p).ToArray(); + return GetCommitteeFromCache(snapshot).Select(p => p.PublicKey).OrderBy(p => p).ToArray(); } public UInt160 GetCommitteeAddress(StoreView snapshot) @@ -302,26 +302,26 @@ public UInt160 GetCommitteeAddress(StoreView snapshot) return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); } - private IEnumerable GetCommitteeFromCache(StoreView snapshot) + private IEnumerable GetCommitteeFromCache(StoreView snapshot) { - return snapshot.Storages[CreateStorageKey(Prefix_Committee)].GetSerializableList(); + return snapshot.Storages[CreateStorageKey(Prefix_Committee)].GetSerializableList(); } internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) { - return ComputeCommitteeMembers(snapshot).Take(ProtocolSettings.Default.ValidatorsCount).OrderBy(p => p).ToArray(); + return ComputeCommitteeMembers(snapshot).Select(p => p.PublicKey).Take(ProtocolSettings.Default.ValidatorsCount).OrderBy(p => p).ToArray(); } - private IEnumerable ComputeCommitteeMembers(StoreView snapshot) + private IEnumerable ComputeCommitteeMembers(StoreView snapshot) { decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; decimal VoterTurnout = votersCount / (decimal)TotalAmount; if (VoterTurnout < EffectiveVoterTurnout) - return Blockchain.StandbyCommittee; + return Blockchain.StandbyCommittee.Select(p => new CommitteeState { PublicKey = p }); var candidates = GetCandidates(snapshot); if (candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) - return Blockchain.StandbyCommittee; - return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); + return Blockchain.StandbyCommittee.Select(p => new CommitteeState { PublicKey = p }); + return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => new CommitteeState { PublicKey = p.PublicKey, Votes = p.Votes }).Take(ProtocolSettings.Default.CommitteeMembersCount); } [ContractMethod(1_00000000, CallFlags.AllowStates)] @@ -329,6 +329,7 @@ public ECPoint[] GetNextBlockValidators(StoreView snapshot) { return GetCommitteeFromCache(snapshot) .Take(ProtocolSettings.Default.ValidatorsCount) + .Select(p => p.PublicKey) .OrderBy(p => p) .ToArray(); } @@ -389,5 +390,25 @@ public StackItem ToStackItem(ReferenceCounter referenceCounter) return new Array(referenceCounter, this.Select(p => new Struct(referenceCounter, new StackItem[] { p.Index, p.GasPerBlock }))); } } + + private sealed class CommitteeState : ISerializable + { + public ECPoint PublicKey; + public BigInteger Votes = BigInteger.Zero; + + public int Size => PublicKey.Size + sizeof(long); + + public void Deserialize(BinaryReader reader) + { + PublicKey = reader.ReadSerializable(); + Votes = reader.ReadInt64(); + } + + public void Serialize(BinaryWriter writer) + { + writer.Write(PublicKey); + writer.WriteVarInt((long)Votes); + } + } } } From f5c17fd3890bf5a33f17c94c17aafbd2773064a6 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 29 Sep 2020 18:45:52 +0800 Subject: [PATCH 40/60] cache committee --- src/neo/Ledger/StorageItem.cs | 2 +- .../SmartContract/Native/Tokens/NeoToken.cs | 52 +++++++++++-------- tests/neo.UnitTests/Consensus/UT_Consensus.cs | 13 ++++- .../Native/Tokens/UT_NeoToken.cs | 9 +++- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/neo/Ledger/StorageItem.cs b/src/neo/Ledger/StorageItem.cs index 5304d926df..40889c9e1c 100644 --- a/src/neo/Ledger/StorageItem.cs +++ b/src/neo/Ledger/StorageItem.cs @@ -86,7 +86,7 @@ void ICloneable.FromReplica(StorageItem replica) if (cache is null) { var interoperable = new T(); - interoperable.FromStackItem(BinarySerializer.Deserialize(value, 16, 34)); + interoperable.FromStackItem(BinarySerializer.Deserialize(value, 21, 34)); cache = interoperable; } value = null; diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 4232a782e1..1d4bf1603c 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -9,7 +9,6 @@ using Neo.VM.Types; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Numerics; using Array = Neo.VM.Types.Array; @@ -124,7 +123,8 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c internal override void Initialize(ApplicationEngine engine) { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Committee), new StorageItem(Blockchain.StandbyCommittee.Select(p => new CommitteeState { PublicKey = p }).ToArray().ToByteArray())); + 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])); // Initialize economic parameters @@ -145,7 +145,8 @@ protected override void OnPersist(ApplicationEngine engine) if (ShouldRefreshCommittee(engine.Snapshot.Height)) { StorageItem storageItem = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Committee)); - storageItem.Value = ComputeCommitteeMembers(engine.Snapshot).ToArray().ToByteArray(); + var cachedCommittee = new CachedCommittee(ComputeCommitteeMembers(engine.Snapshot)); + storageItem.Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096); } } @@ -159,17 +160,17 @@ protected override void PostPersist(ApplicationEngine engine) int n = ProtocolSettings.Default.ValidatorsCount; int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)m); var gasPerBlock = GetGasPerBlock(engine.Snapshot); - var committeeState = GetCommitteeFromCache(engine.Snapshot).ElementAt(index); - var pubkey = committeeState.PublicKey; + var committee = GetCommitteeFromCache(engine.Snapshot).ElementAt(index); + var pubkey = committee.PublicKey; var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); // Record the cumulative reward of the voters of committee var factor = index < n ? 2 : 1; - if (committeeState.Votes > 0) + if (committee.Votes > 0) { - BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / committeeState.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / committee.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index); byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); @@ -302,9 +303,9 @@ public UInt160 GetCommitteeAddress(StoreView snapshot) return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); } - private IEnumerable GetCommitteeFromCache(StoreView snapshot) + private CachedCommittee GetCommitteeFromCache(StoreView snapshot) { - return snapshot.Storages[CreateStorageKey(Prefix_Committee)].GetSerializableList(); + return snapshot.Storages[CreateStorageKey(Prefix_Committee)].GetInteroperable(); } internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) @@ -312,16 +313,16 @@ internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) return ComputeCommitteeMembers(snapshot).Select(p => p.PublicKey).Take(ProtocolSettings.Default.ValidatorsCount).OrderBy(p => p).ToArray(); } - private IEnumerable ComputeCommitteeMembers(StoreView snapshot) + private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> ComputeCommitteeMembers(StoreView snapshot) { decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; decimal VoterTurnout = votersCount / (decimal)TotalAmount; if (VoterTurnout < EffectiveVoterTurnout) - return Blockchain.StandbyCommittee.Select(p => new CommitteeState { PublicKey = p }); + return Blockchain.StandbyCommittee.Select(p => (p, BigInteger.Zero)); var candidates = GetCandidates(snapshot); if (candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) - return Blockchain.StandbyCommittee.Select(p => new CommitteeState { PublicKey = p }); - return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => new CommitteeState { PublicKey = p.PublicKey, Votes = p.Votes }).Take(ProtocolSettings.Default.CommitteeMembersCount); + return Blockchain.StandbyCommittee.Select(p => (p, BigInteger.Zero)); + return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } [ContractMethod(1_00000000, CallFlags.AllowStates)] @@ -391,23 +392,28 @@ public StackItem ToStackItem(ReferenceCounter referenceCounter) } } - private sealed class CommitteeState : ISerializable + public class CachedCommittee : List<(ECPoint PublicKey, BigInteger Votes)>, IInteroperable { - public ECPoint PublicKey; - public BigInteger Votes = BigInteger.Zero; + public CachedCommittee() + { + } - public int Size => PublicKey.Size + sizeof(long); + public CachedCommittee(IEnumerable<(ECPoint PublicKey, BigInteger Votes)> collection) : base(collection) + { + } - public void Deserialize(BinaryReader reader) + public void FromStackItem(StackItem stackItem) { - PublicKey = reader.ReadSerializable(); - Votes = reader.ReadInt64(); + foreach (StackItem item in (Array)stackItem) + { + Struct @struct = (Struct)item; + Add((@struct[0].GetSpan().AsSerializable(), @struct[1].GetInteger())); + } } - public void Serialize(BinaryWriter writer) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { - writer.Write(PublicKey); - writer.WriteVarInt((long)Votes); + return new Array(referenceCounter, this.Select(p => new Struct(referenceCounter, new StackItem[] { p.PublicKey.ToArray(), p.Votes }))); } } } diff --git a/tests/neo.UnitTests/Consensus/UT_Consensus.cs b/tests/neo.UnitTests/Consensus/UT_Consensus.cs index e7ce88be40..038812b072 100644 --- a/tests/neo.UnitTests/Consensus/UT_Consensus.cs +++ b/tests/neo.UnitTests/Consensus/UT_Consensus.cs @@ -17,8 +17,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Reflection; using System.Security.Cryptography; +using static Neo.SmartContract.Native.Tokens.NeoToken; using ECPoint = Neo.Cryptography.ECC.ECPoint; namespace Neo.UnitTests.Consensus @@ -277,10 +279,11 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm Console.WriteLine($"\nContract updated: {updatedContract.ScriptHash}"); // =============================================================== + CachedCommittee cachedCommittee = new CachedCommittee(mockContext.Object.Validators.Select(p => (p, BigInteger.Zero))); mockContext.Object.Snapshot.Storages.Delete(CreateStorageKeyForNativeNeo(14)); mockContext.Object.Snapshot.Storages.Add(CreateStorageKeyForNativeNeo(14), new StorageItem() { - Value = mockContext.Object.Validators.ToByteArray() + Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096) }); mockContext.Object.Snapshot.Commit(); // =============================================================== @@ -298,6 +301,8 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm Console.WriteLine("\n\n=========================="); Console.WriteLine("\nBasic commits Signatures verification"); // Basic tests for understanding signatures and ensuring signatures of commits are correct on tests + + var cmPayloadTemp = GetCommitPayloadModifiedAndSignedCopy(commitPayload, 6, kp_array[6], updatedBlockHashData); Crypto.VerifySignature(originalBlockHashData, cm.Signature, mockContext.Object.Validators[0]).Should().BeFalse(); Crypto.VerifySignature(updatedBlockHashData, cm.Signature, mockContext.Object.Validators[0]).Should().BeFalse(); @@ -414,7 +419,11 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm Console.WriteLine("mockContext Reset for returning Blockchain.Singleton snapshot to original state."); mockContext.Object.Reset(0); mockContext.Object.Snapshot.Storages.Delete(CreateStorageKeyForNativeNeo(14)); - mockContext.Object.Snapshot.Storages.Add(CreateStorageKeyForNativeNeo(14), new StorageItem(Blockchain.StandbyCommittee.ToByteArray())); + cachedCommittee = new CachedCommittee(Blockchain.StandbyCommittee.Select(p => (p, BigInteger.Zero))); + mockContext.Object.Snapshot.Storages.Add(CreateStorageKeyForNativeNeo(14), new StorageItem + { + Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096) + }); mockContext.Object.Snapshot.Commit(); Console.WriteLine("mockContext Reset."); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index de96674c71..07614fe977 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -662,22 +662,27 @@ public void TestClaimGas() // Initialize block snapshot.Storages.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 = Blockchain.StandbyCommittee[i]; + ECPoint member = standbyCommittee[i]; snapshot.Storages.Add(new KeyBuilder(-1, 33).Add(member), new StorageItem(new CandidateState() { Registered = true, Votes = 200 * 10000 })); + cachedCommittee.Add((member, 200 * 10000)); } + snapshot.Storages[new KeyBuilder(-1, 14)].Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096); + var item = snapshot.Storages.GetAndChange(new KeyBuilder(-1, 1), () => new StorageItem()); item.Value = ((BigInteger)2100 * 10000L).ToByteArray(); snapshot.PersistingBlock = new Block { Index = 0 }; Check_PostPersist(snapshot).Should().BeTrue(); - var committee = Blockchain.StandbyCommittee; + var committee = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray(); var accountA = committee[0]; var accountB = committee[ProtocolSettings.Default.CommitteeMembersCount - 1]; NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(accountA).ScriptHash).Should().Be(0); From 29e83addf531c5e61b07438f2980b07342b54dcd Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 30 Sep 2020 11:49:38 +0200 Subject: [PATCH 41/60] Update src/neo/Ledger/StorageItem.cs Co-authored-by: Erik Zhang --- src/neo/Ledger/StorageItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Ledger/StorageItem.cs b/src/neo/Ledger/StorageItem.cs index 40889c9e1c..dd5159fa64 100644 --- a/src/neo/Ledger/StorageItem.cs +++ b/src/neo/Ledger/StorageItem.cs @@ -86,7 +86,7 @@ void ICloneable.FromReplica(StorageItem replica) if (cache is null) { var interoperable = new T(); - interoperable.FromStackItem(BinarySerializer.Deserialize(value, 21, 34)); + interoperable.FromStackItem(BinarySerializer.Deserialize(value, 32, 34)); cache = interoperable; } value = null; From e3b2ee621a7b9b37283686143371f70e8fdf8557 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 10:59:55 +0800 Subject: [PATCH 42/60] fix PostPersist --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- .../SmartContract/Native/Tokens/UT_NeoToken.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 1d4bf1603c..5342ea1942 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -171,7 +171,7 @@ protected override void PostPersist(ApplicationEngine engine) if (committee.Votes > 0) { BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / committee.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L - StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index); + StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index + 1); byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); voterSumRewardPerNEO += (item ?? BigInteger.Zero); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 07614fe977..1f1406f5ac 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -687,7 +687,7 @@ 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(-1, 23).Add(accountA).AddBigEndian(0)); + StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountA).AddBigEndian(1)); new BigInteger(storageItem.Value).Should().Be(31875000000); snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull(); @@ -699,7 +699,7 @@ public void TestClaimGas() NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(1)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(2)); new BigInteger(storageItem.Value).Should().Be(31875000000); // Next block @@ -710,7 +710,7 @@ public void TestClaimGas() 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(-1, 23).Add(committee[2]).AddBigEndian(2)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(3)); new BigInteger(storageItem.Value).Should().Be(31875000000); @@ -721,18 +721,18 @@ public void TestClaimGas() Check_PostPersist(snapshot).Should().BeTrue(); NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2 + 21)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2 + 21 + 1)); new BigInteger(storageItem.Value).Should().Be(31875000000 * 2); var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState { - BalanceHeight = 2, + BalanceHeight = 3, Balance = 200 * 10000 - 2 * 100, VoteTo = committee[2] })); NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(1999800); - BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1); + BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1 + 1); value.Should().Be(1999800 * 31875000000 / 100000000L + (1999800L * 10 * 5 * 29 / 100)); } From 22f1af933fd746aec14f383597f34fc7670ad71a Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 11:50:42 +0800 Subject: [PATCH 43/60] fix ShouldRefreshCommittee & optimize PostPersist --- .../SmartContract/Native/Tokens/NeoToken.cs | 48 +++++++++++-------- .../Native/Tokens/UT_GasToken.cs | 4 +- .../Native/Tokens/UT_NeoToken.cs | 21 +++----- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 5342ea1942..92455a68ee 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -142,7 +142,7 @@ protected override void OnPersist(ApplicationEngine engine) base.OnPersist(engine); // Set next committee - if (ShouldRefreshCommittee(engine.Snapshot.Height)) + if (ShouldRefreshCommittee(engine.Snapshot.PersistingBlock.Index)) { StorageItem storageItem = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Committee)); var cachedCommittee = new CachedCommittee(ComputeCommitteeMembers(engine.Snapshot)); @@ -156,27 +156,33 @@ protected override void PostPersist(ApplicationEngine engine) // Distribute GAS for committee - int m = ProtocolSettings.Default.CommitteeMembersCount; - int n = ProtocolSettings.Default.ValidatorsCount; - int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)m); - var gasPerBlock = GetGasPerBlock(engine.Snapshot); - var committee = GetCommitteeFromCache(engine.Snapshot).ElementAt(index); - var pubkey = committee.PublicKey; - var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); - GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); - - // Record the cumulative reward of the voters of committee - - var factor = index < n ? 2 : 1; - if (committee.Votes > 0) + if (ShouldRefreshCommittee(engine.Snapshot.PersistingBlock.Index)) { - BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / committee.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L - StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index + 1); - byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); - (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); - voterSumRewardPerNEO += (item ?? BigInteger.Zero); - engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); - } + int m = ProtocolSettings.Default.CommitteeMembersCount; + int n = ProtocolSettings.Default.ValidatorsCount; + var gasPerBlock = GetGasPerBlock(engine.Snapshot); + var committee = GetCommitteeFromCache(engine.Snapshot); + for (var index = 0; index < committee.Count; index++) + { + var member = committee.ElementAt(index); + var pubkey = member.PublicKey; + var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); + GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); + + // Record the cumulative reward of the voters of committee + + var factor = index < n ? 2 : 1; + if (member.Votes > 0) + { + BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / member.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index + 1); + byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); + (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); + voterSumRewardPerNEO += (item ?? BigInteger.Zero); + engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); + } + } + } } [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 37871e87c8..8410e7a3c1 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -44,7 +44,7 @@ public void Check_BalanceOfTransferAndBurn() var keyCount = snapshot.Storages.GetChangeSet().Count(); var supply = NativeContract.GAS.TotalSupply(snapshot); - supply.Should().Be(3000000025000000); // 3000000000000000 + 25000000 (neo holder reward) + supply.Should().Be(3000000525000000); // 3000000000000000 + 25000000 * 21 (neo holder reward) // Check unclaim @@ -68,7 +68,7 @@ public void Check_BalanceOfTransferAndBurn() unclaim.State.Should().BeTrue(); supply = NativeContract.GAS.TotalSupply(snapshot); - supply.Should().Be(3000050025000000); + supply.Should().Be(3000050525000000); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 3); // Gas diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 1f1406f5ac..6e83b1cc08 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -312,6 +312,7 @@ public void Check_GetCommittee() } //register more candidates,committee member change + snapshot.PersistingBlock = new Block{ Index = 0}; for (int i = 0; i < ProtocolSettings.Default.CommitteeMembersCount - 1; i++) { Check_RegisterValidator(snapshot, Blockchain.StandbyCommittee[i].ToArray()); @@ -421,7 +422,7 @@ public void Check_CommitteeBonus() var committee = Blockchain.StandbyCommittee; NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[0]).ScriptHash.ToArray()).Should().Be(25000000); NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash.ToArray()).Should().Be(25000000); - NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash.ToArray()).Should().Be(0); + NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash.ToArray()).Should().Be(25000000); } } @@ -699,31 +700,23 @@ public void TestClaimGas() NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(2)); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(1)); new BigInteger(storageItem.Value).Should().Be(31875000000); // Next block - snapshot.PersistingBlock = new Block { Index = 2 }; + snapshot.PersistingBlock = new Block { Index = 21 }; Check_PostPersist(snapshot).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(-1, 23).Add(committee[2]).AddBigEndian(3)); - new BigInteger(storageItem.Value).Should().Be(31875000000); + storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(22)); + new BigInteger(storageItem.Value).Should().Be(31875000000 * 2); // Claim GAS - snapshot.PersistingBlock = new Block { Index = 2 + 21 }; - - Check_PostPersist(snapshot).Should().BeTrue(); - - NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0); - storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(2 + 21 + 1)); - new BigInteger(storageItem.Value).Should().Be(31875000000 * 2); - var account = Contract.CreateSignatureContract(committee[2]).ScriptHash; snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState { @@ -732,7 +725,7 @@ public void TestClaimGas() VoteTo = committee[2] })); NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(1999800); - BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 2 + 28 + 1 + 1); + BigInteger value = NativeContract.NEO.UnclaimedGas(snapshot, account, 29 + 3); value.Should().Be(1999800 * 31875000000 / 100000000L + (1999800L * 10 * 5 * 29 / 100)); } From 3d5065d7d71c1f7244d42b3bc4e1f7051e67ac48 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 11:53:53 +0800 Subject: [PATCH 44/60] add CommitteeEpoch --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 4 +++- .../neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 92455a68ee..fd7a4bd481 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -35,6 +35,8 @@ public sealed class NeoToken : Nep5Token private const byte CommitteeRewardRatio = 5; private const byte VoterRewardRatio = 85; + private int CommitteeEpoch = ProtocolSettings.Default.CommitteeMembersCount; + internal NeoToken() { this.TotalAmount = 100000000 * Factor; @@ -119,7 +121,7 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c } } - private bool ShouldRefreshCommittee(uint height) => height % ProtocolSettings.Default.CommitteeMembersCount == 0; + private bool ShouldRefreshCommittee(uint height) => height % CommitteeEpoch == 0; internal override void Initialize(ApplicationEngine engine) { diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 6e83b1cc08..be80487189 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -312,7 +312,7 @@ public void Check_GetCommittee() } //register more candidates,committee member change - snapshot.PersistingBlock = new Block{ Index = 0}; + snapshot.PersistingBlock = new Block { Index = 0 }; for (int i = 0; i < ProtocolSettings.Default.CommitteeMembersCount - 1; i++) { Check_RegisterValidator(snapshot, Blockchain.StandbyCommittee[i].ToArray()); From 50e16636ee5c1b755564d9affd254dea196749fd Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 12:00:43 +0800 Subject: [PATCH 45/60] fix CalculateBonus --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index fd7a4bd481..0ee58f9ce2 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -73,6 +73,7 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v { if (value.IsZero || start >= end) return BigInteger.Zero; if (value.Sign < 0) throw new ArgumentOutOfRangeException(nameof(value)); + if (start > 0 && (start - 1) / CommitteeEpoch == (end - 1) / CommitteeEpoch) return BigInteger.Zero; BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); if (vote is null) return neoHolderReward; @@ -184,7 +185,7 @@ protected override void PostPersist(ApplicationEngine engine) engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); } } - } + } } [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] From aa688caec71171af16a0a8d8975ad6bf6b9bd9df Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 13:04:08 +0800 Subject: [PATCH 46/60] fix PostPersist --- .../SmartContract/Native/Tokens/NeoToken.cs | 30 +++++++++---------- .../Native/Tokens/UT_GasToken.cs | 4 +-- .../Native/Tokens/UT_NeoToken.cs | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 0ee58f9ce2..1635bba3e0 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -73,10 +73,9 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v { if (value.IsZero || start >= end) return BigInteger.Zero; if (value.Sign < 0) throw new ArgumentOutOfRangeException(nameof(value)); - if (start > 0 && (start - 1) / CommitteeEpoch == (end - 1) / CommitteeEpoch) return BigInteger.Zero; BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); - if (vote is null) return neoHolderReward; + if (vote is null || (start > 0 && (start - 1) / CommitteeEpoch == (end - 1) / CommitteeEpoch)) return neoHolderReward; byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).ToArray(); byte[] keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start).ToArray(); @@ -159,27 +158,28 @@ protected override void PostPersist(ApplicationEngine engine) // Distribute GAS for committee + int m = ProtocolSettings.Default.CommitteeMembersCount; + int n = ProtocolSettings.Default.ValidatorsCount; + int index = (int)(engine.Snapshot.PersistingBlock.Index % (uint)m); + var gasPerBlock = GetGasPerBlock(engine.Snapshot); + var committee = GetCommitteeFromCache(engine.Snapshot); + var pubkey = committee.ElementAt(index).PublicKey; + var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); + GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); + + // Record the cumulative reward of the voters of committee + if (ShouldRefreshCommittee(engine.Snapshot.PersistingBlock.Index)) { - int m = ProtocolSettings.Default.CommitteeMembersCount; - int n = ProtocolSettings.Default.ValidatorsCount; - var gasPerBlock = GetGasPerBlock(engine.Snapshot); - var committee = GetCommitteeFromCache(engine.Snapshot); - for (var index = 0; index < committee.Count; index++) + for (index = 0; index < committee.Count; index++) { var member = committee.ElementAt(index); - var pubkey = member.PublicKey; - var account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); - GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100); - - // Record the cumulative reward of the voters of committee - var factor = index < n ? 2 : 1; if (member.Votes > 0) { BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / member.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L - StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).AddBigEndian(engine.Snapshot.PersistingBlock.Index + 1); - byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray(); + StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(member.PublicKey).AddBigEndian(engine.Snapshot.PersistingBlock.Index + 1); + byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(member.PublicKey).ToArray(); (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); voterSumRewardPerNEO += (item ?? BigInteger.Zero); engine.Snapshot.Storages.Add(voterRewardKey, new StorageItem(voterSumRewardPerNEO)); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 8410e7a3c1..37871e87c8 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -44,7 +44,7 @@ public void Check_BalanceOfTransferAndBurn() var keyCount = snapshot.Storages.GetChangeSet().Count(); var supply = NativeContract.GAS.TotalSupply(snapshot); - supply.Should().Be(3000000525000000); // 3000000000000000 + 25000000 * 21 (neo holder reward) + supply.Should().Be(3000000025000000); // 3000000000000000 + 25000000 (neo holder reward) // Check unclaim @@ -68,7 +68,7 @@ public void Check_BalanceOfTransferAndBurn() unclaim.State.Should().BeTrue(); supply = NativeContract.GAS.TotalSupply(snapshot); - supply.Should().Be(3000050525000000); + supply.Should().Be(3000050025000000); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 3); // Gas diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index be80487189..fdfdf77e5e 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -422,7 +422,7 @@ public void Check_CommitteeBonus() var committee = Blockchain.StandbyCommittee; NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[0]).ScriptHash.ToArray()).Should().Be(25000000); NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash.ToArray()).Should().Be(25000000); - NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash.ToArray()).Should().Be(25000000); + NativeContract.GAS.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash.ToArray()).Should().Be(0); } } From 6218108b014c26856b67d5d8388b0549fb25915b Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 13:09:39 +0800 Subject: [PATCH 47/60] optimize CalculateBonus --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 1635bba3e0..ee26179d01 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -35,8 +35,6 @@ public sealed class NeoToken : Nep5Token private const byte CommitteeRewardRatio = 5; private const byte VoterRewardRatio = 85; - private int CommitteeEpoch = ProtocolSettings.Default.CommitteeMembersCount; - internal NeoToken() { this.TotalAmount = 100000000 * Factor; @@ -75,7 +73,7 @@ private BigInteger CalculateBonus(StoreView snapshot, ECPoint vote, BigInteger v if (value.Sign < 0) throw new ArgumentOutOfRangeException(nameof(value)); BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, value, start, end); - if (vote is null || (start > 0 && (start - 1) / CommitteeEpoch == (end - 1) / CommitteeEpoch)) return neoHolderReward; + if (vote is null) return neoHolderReward; byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).ToArray(); byte[] keyStart = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(vote).AddBigEndian(start).ToArray(); @@ -121,7 +119,7 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c } } - private bool ShouldRefreshCommittee(uint height) => height % CommitteeEpoch == 0; + private bool ShouldRefreshCommittee(uint height) => height % ProtocolSettings.Default.CommitteeMembersCount == 0; internal override void Initialize(ApplicationEngine engine) { From 42535020318bab7381ce771ddfead8b3c22557a4 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Fri, 9 Oct 2020 13:14:34 +0800 Subject: [PATCH 48/60] optimize PostPersist --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index ee26179d01..292dcfa654 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -169,13 +169,14 @@ protected override void PostPersist(ApplicationEngine engine) if (ShouldRefreshCommittee(engine.Snapshot.PersistingBlock.Index)) { + BigInteger voterRewardOfEachCommittee = gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100; // Zoom in 100000000 times, and the final calculation should be divided 100000000L for (index = 0; index < committee.Count; index++) { var member = committee.ElementAt(index); var factor = index < n ? 2 : 1; if (member.Votes > 0) { - BigInteger voterSumRewardPerNEO = factor * gasPerBlock * VoterRewardRatio * 100000000L * m / (m + n) / 100 / member.Votes; // Zoom in 100000000 times, and the final calculation should be divided 100000000L + BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / member.Votes; StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(member.PublicKey).AddBigEndian(engine.Snapshot.PersistingBlock.Index + 1); byte[] border = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(member.PublicKey).ToArray(); (_, var item) = engine.Snapshot.Storages.FindRange(voterRewardKey.ToArray(), border, SeekDirection.Backward).FirstOrDefault(); From d06c1cb07604998bfad1183142765c26339ae25e Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sat, 10 Oct 2020 15:49:57 +0800 Subject: [PATCH 49/60] Update NeoToken.cs --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 292dcfa654..64999aa6af 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -145,8 +145,9 @@ protected override void OnPersist(ApplicationEngine engine) if (ShouldRefreshCommittee(engine.Snapshot.PersistingBlock.Index)) { StorageItem storageItem = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Committee)); - var cachedCommittee = new CachedCommittee(ComputeCommitteeMembers(engine.Snapshot)); - storageItem.Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096); + var cachedCommittee = storageItem.GetInteroperable(); + cachedCommittee.Clear(); + cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot)); } } From 7ba5e247977e74f0517209bf54a6c7940afddd31 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Mon, 19 Oct 2020 16:26:00 +0800 Subject: [PATCH 50/60] add comments for trigger github action --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 85c5cc9af1..4e85774485 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -167,7 +167,7 @@ protected override void PostPersist(ApplicationEngine engine) for (index = 0; index < committee.Count; index++) { var member = committee.ElementAt(index); - var factor = index < n ? 2 : 1; + var factor = index < n ? 2 : 1; // The `voter` rewards of validator will double than other committee's if (member.Votes > 0) { BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / member.Votes; From e8c8044b05d2d23f3e27e854fa1cb0603aecfb00 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 20 Oct 2020 18:36:40 +0800 Subject: [PATCH 51/60] Allow standby can be voted --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 4e85774485..e3cd07ead7 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -318,11 +318,11 @@ internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) { decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; decimal VoterTurnout = votersCount / (decimal)TotalAmount; - if (VoterTurnout < EffectiveVoterTurnout) - return Blockchain.StandbyCommittee.Select(p => (p, BigInteger.Zero)); var candidates = GetCandidates(snapshot); + if (VoterTurnout < EffectiveVoterTurnout) + return Blockchain.StandbyCommittee.Select(p => (p, candidates.FirstOrDefault(k => k.PublicKey.Equals(p)).Votes)); if (candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) - return Blockchain.StandbyCommittee.Select(p => (p, BigInteger.Zero)); + return Blockchain.StandbyCommittee.Select(p => (p, candidates.FirstOrDefault(k => k.PublicKey.Equals(p)).Votes)); return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } From 95acd308fa38373fe395b233102900eb73f5b37c Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 27 Oct 2020 15:25:39 +0800 Subject: [PATCH 52/60] optimize --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index e3cd07ead7..710e90d45d 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -319,9 +319,7 @@ internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; decimal VoterTurnout = votersCount / (decimal)TotalAmount; var candidates = GetCandidates(snapshot); - if (VoterTurnout < EffectiveVoterTurnout) - return Blockchain.StandbyCommittee.Select(p => (p, candidates.FirstOrDefault(k => k.PublicKey.Equals(p)).Votes)); - if (candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) + if (VoterTurnout < EffectiveVoterTurnout || candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) return Blockchain.StandbyCommittee.Select(p => (p, candidates.FirstOrDefault(k => k.PublicKey.Equals(p)).Votes)); return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } From 5d5837ea9b3c3b419a323d3793a367b00ebda3e3 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 27 Oct 2020 09:46:46 +0100 Subject: [PATCH 53/60] rename local variable --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 710e90d45d..5ab6e5f10e 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -317,9 +317,9 @@ internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> ComputeCommitteeMembers(StoreView snapshot) { decimal votersCount = (decimal)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_VotersCount)]; - decimal VoterTurnout = votersCount / (decimal)TotalAmount; + decimal voterTurnout = votersCount / (decimal)TotalAmount; var candidates = GetCandidates(snapshot); - if (VoterTurnout < EffectiveVoterTurnout || candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) + if (voterTurnout < EffectiveVoterTurnout || candidates.Length < ProtocolSettings.Default.CommitteeMembersCount) return Blockchain.StandbyCommittee.Select(p => (p, candidates.FirstOrDefault(k => k.PublicKey.Equals(p)).Votes)); return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } From 990d8d5a3925a813e88188a34d38ff0563c84db8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 27 Oct 2020 10:03:47 +0100 Subject: [PATCH 54/60] Optimize Unregister Candidate --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 5ab6e5f10e..7c8bf7e0ff 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -235,7 +235,7 @@ 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; + if (!engine.Snapshot.Storages.Contains(key)) return true; StorageItem item = engine.Snapshot.Storages.GetAndChange(key); CandidateState state = item.GetInteroperable(); state.Registered = false; From 898f21cfbfd9cc03ec5f4d3b4ebaf43490bab94d Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 27 Oct 2020 16:16:50 +0100 Subject: [PATCH 55/60] Revert --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 7c8bf7e0ff..5ab6e5f10e 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -235,7 +235,7 @@ 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.Contains(key)) return true; + if (engine.Snapshot.Storages.TryGet(key) is null) return true; StorageItem item = engine.Snapshot.Storages.GetAndChange(key); CandidateState state = item.GetInteroperable(); state.Registered = false; From 44bdd5cd44b5ac3e569553257548d2511a8df906 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 29 Oct 2020 11:17:44 +0800 Subject: [PATCH 56/60] add ut --- .../Native/Tokens/UT_NeoToken.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 3822fe4260..d7e117b870 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -570,6 +570,33 @@ public void TestGetCandidates2() NativeContract.NEO.GetCandidates(snapshot).Length.Should().Be(1); } + [TestMethod] + public void TestCheckCandidate() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + var committee = NativeContract.NEO.GetCommittee(snapshot); + var point = committee[0].EncodePoint(true); + + // Prepare Prefix_VoterRewardPerCommittee + var storageKey = new KeyBuilder(-1, 23).Add(committee[0]).AddBigEndian(20); + snapshot.Storages.Add(storageKey, new StorageItem(new BigInteger(1000))); + + // Prepare Candidate + storageKey = new KeyBuilder(-1, 33).Add(committee[0]); + snapshot.Storages.Add(storageKey, new StorageItem(new CandidateState { Registered = true, Votes = BigInteger.One })); + + // Unregister candidate + var ret = Check_UnregisterCandidate(snapshot, point); + ret.State.Should().BeTrue(); + ret.Result.Should().BeTrue(); + + snapshot.PersistingBlock = new Block { Index = 21 }; + Check_PostPersist(snapshot).Should().BeTrue(); + + storageKey = new KeyBuilder(-1, 23).Add(committee[0]); + snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); + } + [TestMethod] public void TestGetCommittee() { From 4d4986d1e4bc688f86adf711d2122b162aa85aff Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 29 Oct 2020 11:52:04 +0800 Subject: [PATCH 57/60] fix ut --- .../Native/Tokens/UT_NeoToken.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index d7e117b870..13ac48d1a1 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -585,12 +585,28 @@ public void TestCheckCandidate() storageKey = new KeyBuilder(-1, 33).Add(committee[0]); snapshot.Storages.Add(storageKey, new StorageItem(new CandidateState { Registered = true, Votes = BigInteger.One })); - // Unregister candidate + storageKey = new KeyBuilder(-1, 23).Add(committee[0]); + snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); + + + // Pre-persist + snapshot.PersistingBlock = new Block { Index = 21 }; + Check_OnPersist(snapshot); + + // Clear votes + storageKey = new KeyBuilder(-1, 33).Add(committee[0]); + snapshot.Storages.GetAndChange(storageKey).GetInteroperable().Votes = BigInteger.Zero; + + // Unregister candidate, remove var ret = Check_UnregisterCandidate(snapshot, point); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); - snapshot.PersistingBlock = new Block { Index = 21 }; + storageKey = new KeyBuilder(-1, 23).Add(committee[0]); + snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(0); + + + // Post-persist Check_PostPersist(snapshot).Should().BeTrue(); storageKey = new KeyBuilder(-1, 23).Add(committee[0]); From ca174f0c520afbb6479264ececf02c0ca3c617b0 Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Thu, 29 Oct 2020 11:56:36 +0800 Subject: [PATCH 58/60] format --- tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 13ac48d1a1..31697ec6cb 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -588,7 +588,6 @@ public void TestCheckCandidate() storageKey = new KeyBuilder(-1, 23).Add(committee[0]); snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1); - // Pre-persist snapshot.PersistingBlock = new Block { Index = 21 }; Check_OnPersist(snapshot); @@ -605,7 +604,6 @@ public void TestCheckCandidate() storageKey = new KeyBuilder(-1, 23).Add(committee[0]); snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(0); - // Post-persist Check_PostPersist(snapshot).Should().BeTrue(); From c23c3ba63959da3ea34b18503f9cbd7e7959fa0d Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 29 Oct 2020 09:08:45 +0100 Subject: [PATCH 59/60] Conflicts --- .../neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index cc892952cc..77b6805622 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -859,7 +859,7 @@ internal static bool Check_OnPersist(StoreView snapshot) { ECPoint[] committees = NativeContract.NEO.GetCommittee(snapshot); UInt160 committeesMultisign = Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); - var engine = ApplicationEngine.Create(TriggerType.System, + var engine = ApplicationEngine.Create(TriggerType.OnPersist, new Nep5NativeContractExtensions.ManualWitness(committeesMultisign), snapshot); engine.LoadScript(NativeContract.NEO.Script); @@ -877,7 +877,7 @@ internal static bool Check_PostPersist(StoreView snapshot) { ECPoint[] committees = NativeContract.NEO.GetCommittee(snapshot); UInt160 committeesMultisign = Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); - var engine = ApplicationEngine.Create(TriggerType.System, + var engine = ApplicationEngine.Create(TriggerType.PostPersist, new Nep5NativeContractExtensions.ManualWitness(committeesMultisign), snapshot); engine.LoadScript(NativeContract.NEO.Script); From 5e186730742fd1a7f767a7563dadb9e0509248d1 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Sun, 1 Nov 2020 09:40:11 +0800 Subject: [PATCH 60/60] Update src/neo/SmartContract/Native/Tokens/NeoToken.cs Co-authored-by: Erik Zhang --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index d2ee532a78..eb5b0f14e4 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -110,7 +110,7 @@ private void CheckCandidate(StoreView snapshot, ECPoint pubkey, CandidateState c { if (!candidate.Registered && candidate.Votes.IsZero) { - foreach (var (rewardKey, _) in snapshot.Storages.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray())) + 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)); }