diff --git a/src/neo/Consensus/ConsensusContext.cs b/src/neo/Consensus/ConsensusContext.cs index 7b1cc8b3d0..763fa2e77f 100644 --- a/src/neo/Consensus/ConsensusContext.cs +++ b/src/neo/Consensus/ConsensusContext.cs @@ -109,10 +109,10 @@ public void Deserialize(BinaryReader reader) ViewNumber = reader.ReadByte(); TransactionHashes = reader.ReadSerializableArray(); Transaction[] transactions = reader.ReadSerializableArray(Block.MaxTransactionsPerBlock); - PreparationPayloads = reader.ReadNullableArray(ProtocolSettings.Default.MaxValidatorsCount); - CommitPayloads = reader.ReadNullableArray(ProtocolSettings.Default.MaxValidatorsCount); - ChangeViewPayloads = reader.ReadNullableArray(ProtocolSettings.Default.MaxValidatorsCount); - LastChangeViewPayloads = reader.ReadNullableArray(ProtocolSettings.Default.MaxValidatorsCount); + PreparationPayloads = reader.ReadNullableArray(ProtocolSettings.Default.ValidatorsCount); + CommitPayloads = reader.ReadNullableArray(ProtocolSettings.Default.ValidatorsCount); + ChangeViewPayloads = reader.ReadNullableArray(ProtocolSettings.Default.ValidatorsCount); + LastChangeViewPayloads = reader.ReadNullableArray(ProtocolSettings.Default.ValidatorsCount); if (TransactionHashes.Length == 0 && !RequestSentOrReceived) TransactionHashes = null; Transactions = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash); diff --git a/src/neo/Consensus/RecoveryMessage.cs b/src/neo/Consensus/RecoveryMessage.cs index cadb137b80..b082f2aeb2 100644 --- a/src/neo/Consensus/RecoveryMessage.cs +++ b/src/neo/Consensus/RecoveryMessage.cs @@ -31,7 +31,7 @@ public RecoveryMessage() : base(ConsensusMessageType.RecoveryMessage) public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); - ChangeViewMessages = reader.ReadSerializableArray(ProtocolSettings.Default.MaxValidatorsCount).ToDictionary(p => (int)p.ValidatorIndex); + ChangeViewMessages = reader.ReadSerializableArray(ProtocolSettings.Default.ValidatorsCount).ToDictionary(p => (int)p.ValidatorIndex); if (reader.ReadBoolean()) PrepareRequestMessage = reader.ReadSerializable(); else @@ -41,8 +41,8 @@ public override void Deserialize(BinaryReader reader) PreparationHash = new UInt256(reader.ReadFixedBytes(preparationHashSize)); } - PreparationMessages = reader.ReadSerializableArray(ProtocolSettings.Default.MaxValidatorsCount).ToDictionary(p => (int)p.ValidatorIndex); - CommitMessages = reader.ReadSerializableArray(ProtocolSettings.Default.MaxValidatorsCount).ToDictionary(p => (int)p.ValidatorIndex); + PreparationMessages = reader.ReadSerializableArray(ProtocolSettings.Default.ValidatorsCount).ToDictionary(p => (int)p.ValidatorIndex); + CommitMessages = reader.ReadSerializableArray(ProtocolSettings.Default.ValidatorsCount).ToDictionary(p => (int)p.ValidatorIndex); } internal ConsensusPayload[] GetChangeViewPayloads(ConsensusContext context, ConsensusPayload payload) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index f4f0c6879e..0ac37aa5ab 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -32,8 +32,8 @@ public class RelayResult { public IInventory Inventory; public VerifyResult Resu public const uint DecrementInterval = 2000000; public static readonly uint[] GenerationAmount = { 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; public static readonly TimeSpan TimePerBlock = TimeSpan.FromMilliseconds(MillisecondsPerBlock); - public static readonly ECPoint[] StandbyCommittee = ProtocolSettings.Default.StandbyCommittee.Take(ProtocolSettings.Default.MaxCommitteeMembersCount).Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray(); - public static readonly ECPoint[] StandbyValidators = StandbyCommittee.Take(ProtocolSettings.Default.MaxValidatorsCount).ToArray(); + public static readonly ECPoint[] StandbyCommittee = ProtocolSettings.Default.StandbyCommittee.Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray(); + public static readonly ECPoint[] StandbyValidators = StandbyCommittee[0..ProtocolSettings.Default.ValidatorsCount]; public static readonly Block GenesisBlock = new Block { diff --git a/src/neo/Network/P2P/Payloads/ConsensusData.cs b/src/neo/Network/P2P/Payloads/ConsensusData.cs index 7bbee151fb..8a63f2350f 100644 --- a/src/neo/Network/P2P/Payloads/ConsensusData.cs +++ b/src/neo/Network/P2P/Payloads/ConsensusData.cs @@ -27,7 +27,7 @@ public UInt256 Hash void ISerializable.Deserialize(BinaryReader reader) { - PrimaryIndex = (uint)reader.ReadVarInt((ulong)ProtocolSettings.Default.MaxValidatorsCount - 1); + PrimaryIndex = (uint)reader.ReadVarInt((ulong)ProtocolSettings.Default.ValidatorsCount - 1); Nonce = reader.ReadUInt64(); } diff --git a/src/neo/ProtocolSettings.cs b/src/neo/ProtocolSettings.cs index e004b637a8..79a422f060 100644 --- a/src/neo/ProtocolSettings.cs +++ b/src/neo/ProtocolSettings.cs @@ -10,8 +10,8 @@ public class ProtocolSettings public uint Magic { get; } public byte AddressVersion { get; } public string[] StandbyCommittee { get; } - public byte MaxCommitteeMembersCount { get; } - public byte MaxValidatorsCount { get; } + public int CommitteeMembersCount { get; } + public int ValidatorsCount { get; } public string[] SeedList { get; } public uint MillisecondsPerBlock { get; } public int MemoryPoolMaxTransactions { get; } @@ -78,8 +78,8 @@ private ProtocolSettings(IConfigurationSection section) "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" }; - this.MaxCommitteeMembersCount = section.GetValue("MaxCommitteeMembersCount", (byte)21); - this.MaxValidatorsCount = section.GetValue("MaxValidatorsCount", (byte)7); + this.CommitteeMembersCount = StandbyCommittee.Length; + this.ValidatorsCount = section.GetValue("ValidatorsCount", (byte)7); IConfigurationSection section_sl = section.GetSection("SeedList"); if (section_sl.Exists()) this.SeedList = section_sl.GetChildren().Select(p => p.Get()).ToArray(); diff --git a/src/neo/SmartContract/Native/KeyBuilder.cs b/src/neo/SmartContract/Native/KeyBuilder.cs index a5cafedfd9..79ae513df8 100644 --- a/src/neo/SmartContract/Native/KeyBuilder.cs +++ b/src/neo/SmartContract/Native/KeyBuilder.cs @@ -37,6 +37,14 @@ unsafe public KeyBuilder Add(T key) where T : unmanaged return Add(new ReadOnlySpan(&key, sizeof(T))); } + public byte[] ToArray() + { + using (stream) + { + return StorageKey.CreateSearchPrefix(id, stream.ToArray()); + } + } + public static implicit operator StorageKey(KeyBuilder builder) { using (builder.stream) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index aef7abd14d..fa86ca70d5 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -21,6 +21,9 @@ public sealed class NeoToken : Nep5Token public override byte Decimals => 0; public BigInteger TotalAmount { get; } + public const decimal EffectiveVoterTurnout = 0.2M; + + private const byte Prefix_VotersCount = 1; private const byte Prefix_Candidate = 33; private const byte Prefix_NextValidators = 14; @@ -40,9 +43,10 @@ protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 acco if (amount.IsZero) return; if (state.VoteTo != null) { - StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(state.VoteTo)); - CandidateState state_validator = storage_validator.GetInteroperable(); - state_validator.Votes += amount; + engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(state.VoteTo)).GetInteroperable().Votes += amount; + StorageItem item = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)); + BigInteger votersCount = new BigInteger(item.Value) + amount; + item.Value = votersCount.ToByteArray(); } } @@ -87,19 +91,8 @@ private BigInteger CalculateBonus(BigInteger value, uint start, uint end) internal override void Initialize(ApplicationEngine engine) { - BigInteger amount = TotalAmount; - for (int i = 0; i < Blockchain.StandbyCommittee.Length; i++) - { - ECPoint pubkey = Blockchain.StandbyCommittee[i]; - RegisterCandidateInternal(engine.Snapshot, pubkey); - BigInteger balance = TotalAmount / 2 / (Blockchain.StandbyValidators.Length * 2 + (Blockchain.StandbyCommittee.Length - Blockchain.StandbyValidators.Length)); - if (i < Blockchain.StandbyValidators.Length) balance *= 2; - UInt160 account = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); - Mint(engine, account, balance); - VoteInternal(engine.Snapshot, account, pubkey); - amount -= balance; - } - Mint(engine, Blockchain.GetConsensusAddress(Blockchain.StandbyValidators), amount); + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(new byte[0])); + Mint(engine, Blockchain.GetConsensusAddress(Blockchain.StandbyValidators), TotalAmount); } protected override void OnPersist(ApplicationEngine engine) @@ -123,16 +116,11 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; - RegisterCandidateInternal(engine.Snapshot, pubkey); - return true; - } - - private void RegisterCandidateInternal(StoreView snapshot, ECPoint pubkey) - { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem(new CandidateState())); + StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable(); state.Registered = true; + return true; } [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] @@ -155,30 +143,35 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) return false; - return VoteInternal(engine.Snapshot, account, voteTo); - } - - private bool VoteInternal(StoreView snapshot, UInt160 account, ECPoint voteTo) - { StorageKey key_account = CreateStorageKey(Prefix_Account).Add(account); - if (snapshot.Storages.TryGet(key_account) is null) return false; - StorageItem storage_account = snapshot.Storages.GetAndChange(key_account); + if (engine.Snapshot.Storages.TryGet(key_account) is null) return false; + StorageItem storage_account = engine.Snapshot.Storages.GetAndChange(key_account); NeoAccountState state_account = storage_account.GetInteroperable(); + if (state_account.VoteTo is null ^ voteTo is null) + { + StorageItem item = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)); + BigInteger votersCount = new BigInteger(item.Value); + if (state_account.VoteTo is null) + votersCount += state_account.Balance; + else + votersCount -= state_account.Balance; + item.Value = votersCount.ToByteArray(); + } if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); - StorageItem storage_validator = snapshot.Storages.GetAndChange(key); + StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; if (!state_validator.Registered && state_validator.Votes.IsZero) - snapshot.Storages.Delete(key); + engine.Snapshot.Storages.Delete(key); } state_account.VoteTo = voteTo; if (voteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(voteTo); - if (snapshot.Storages.TryGet(key) is null) return false; - StorageItem storage_validator = snapshot.Storages.GetAndChange(key); + if (engine.Snapshot.Storages.TryGet(key) is null) return false; + StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable(); if (!state_validator.Registered) return false; state_validator.Votes += state_account.Balance; @@ -189,29 +182,24 @@ private bool VoteInternal(StoreView snapshot, UInt160 account, ECPoint voteTo) [ContractMethod(1_00000000, CallFlags.AllowStates)] public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(StoreView snapshot) { - return GetCandidatesInternal(snapshot).ToArray(); - } - - private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetCandidatesInternal(StoreView snapshot) - { - byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Candidate }); + 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)); + )).Where(p => p.Item2.Registered).Select(p => (p.Item1, p.Item2.Votes)).ToArray(); } [ContractMethod(1_00000000, CallFlags.AllowStates)] public ECPoint[] GetValidators(StoreView snapshot) { - return GetCommitteeMembers(snapshot, ProtocolSettings.Default.MaxValidatorsCount).OrderBy(p => p).ToArray(); + return GetCommitteeMembers(snapshot).Take(ProtocolSettings.Default.ValidatorsCount).OrderBy(p => p).ToArray(); } [ContractMethod(1_00000000, CallFlags.AllowStates)] public ECPoint[] GetCommittee(StoreView snapshot) { - return GetCommitteeMembers(snapshot, ProtocolSettings.Default.MaxCommitteeMembersCount).OrderBy(p => p).ToArray(); + return GetCommitteeMembers(snapshot).OrderBy(p => p).ToArray(); } public UInt160 GetCommitteeAddress(StoreView snapshot) @@ -220,9 +208,16 @@ public UInt160 GetCommitteeAddress(StoreView snapshot) return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash(); } - private IEnumerable GetCommitteeMembers(StoreView snapshot, int count) + private IEnumerable GetCommitteeMembers(StoreView snapshot) { - return GetCandidatesInternal(snapshot).OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => p.PublicKey).Take(count); + decimal votersCount = (decimal)new BigInteger(snapshot.Storages[CreateStorageKey(Prefix_VotersCount)].Value); + decimal VoterTurnout = votersCount / (decimal)TotalAmount; + if (VoterTurnout < EffectiveVoterTurnout) + return Blockchain.StandbyCommittee; + 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); } [ContractMethod(1_00000000, CallFlags.AllowStates)] diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 17e45ed08c..380bdb65a6 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -49,16 +49,16 @@ public void Check_BalanceOfTransferAndBurn() // Check unclaim var unclaim = UT_NeoToken.Check_UnclaimedGas(snapshot, from); - unclaim.Value.Should().Be(new BigInteger(300000048000)); + unclaim.Value.Should().Be(new BigInteger(600000000000)); unclaim.State.Should().BeTrue(); // Transfer NativeContract.NEO.Transfer(snapshot, from, to, BigInteger.Zero, true).Should().BeTrue(); - NativeContract.NEO.BalanceOf(snapshot, from).Should().Be(50000008); + NativeContract.NEO.BalanceOf(snapshot, from).Should().Be(100000000); NativeContract.NEO.BalanceOf(snapshot, to).Should().Be(0); - NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(3000300000048000); + NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(30006000_00000000); NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(0); // Check unclaim @@ -68,7 +68,7 @@ public void Check_BalanceOfTransferAndBurn() unclaim.State.Should().BeTrue(); supply = NativeContract.GAS.TotalSupply(snapshot); - supply.Should().Be(3000300000048000); + supply.Should().Be(30006000_00000000); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 3); // Gas @@ -76,13 +76,13 @@ public void Check_BalanceOfTransferAndBurn() keyCount = snapshot.Storages.GetChangeSet().Count(); - NativeContract.GAS.Transfer(snapshot, from, to, 3000300000048000, false).Should().BeFalse(); // Not signed - NativeContract.GAS.Transfer(snapshot, from, to, 3000300000048001, true).Should().BeFalse(); // More than balance - NativeContract.GAS.Transfer(snapshot, from, to, 3000300000048000, true).Should().BeTrue(); // All balance + NativeContract.GAS.Transfer(snapshot, from, to, 30006000_00000000, false).Should().BeFalse(); // Not signed + NativeContract.GAS.Transfer(snapshot, from, to, 30006000_00000001, true).Should().BeFalse(); // More than balance + NativeContract.GAS.Transfer(snapshot, from, to, 30006000_00000000, true).Should().BeTrue(); // All balance // Balance of - NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000300000048000); + NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(30006000_00000000); NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(0); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); // All @@ -98,19 +98,19 @@ public void Check_BalanceOfTransferAndBurn() // Burn more than expected Assert.ThrowsException(() => - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000300000048001))); + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(30006000_00000001))); // Real burn NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(1)); - NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000300000047999); + NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(30005999_99999999); keyCount.Should().Be(snapshot.Storages.GetChangeSet().Count()); // Burn all - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000300000047999)); + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(30005999_99999999)); (keyCount - 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 1cce77536e..846f03d5cc 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -84,7 +84,7 @@ public void Check_UnclaimedGas() byte[] from = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); var unclaim = Check_UnclaimedGas(snapshot, from); - unclaim.Value.Should().Be(new BigInteger(300000048000)); + unclaim.Value.Should().Be(new BigInteger(600000000000)); unclaim.State.Should().BeTrue(); unclaim = Check_UnclaimedGas(snapshot, new byte[19]); @@ -116,16 +116,8 @@ public void Check_RegisterValidator() // Check GetRegisteredValidators - var members = NativeContract.NEO.GetCandidates(snapshot).OrderBy(u => u.PublicKey).ToArray(); - var check = Blockchain.StandbyCommittee.Select(u => u.EncodePoint(true)).ToList(); - check.Add(point); // Add the new member - - for (int x = 0; x < members.Length; x++) - { - Assert.AreEqual(1, check.RemoveAll(u => u.SequenceEqual(members[x].PublicKey.EncodePoint(true)))); - } - - Assert.AreEqual(0, check.Count); + var members = NativeContract.NEO.GetCandidates(snapshot); + Assert.AreEqual(2, members.Length); } [TestMethod] @@ -143,14 +135,14 @@ public void Check_Transfer() // Check unclaim var unclaim = Check_UnclaimedGas(snapshot, from); - unclaim.Value.Should().Be(new BigInteger(300000048000)); + unclaim.Value.Should().Be(new BigInteger(600000000000)); unclaim.State.Should().BeTrue(); // Transfer NativeContract.NEO.Transfer(snapshot, from, to, BigInteger.One, false).Should().BeFalse(); // Not signed NativeContract.NEO.Transfer(snapshot, from, to, BigInteger.One, true).Should().BeTrue(); - NativeContract.NEO.BalanceOf(snapshot, from).Should().Be(50000007); + NativeContract.NEO.BalanceOf(snapshot, from).Should().Be(99999999); NativeContract.NEO.BalanceOf(snapshot, to).Should().Be(1); // Check unclaim @@ -186,7 +178,7 @@ public void Check_BalanceOf() var snapshot = Blockchain.Singleton.GetSnapshot(); byte[] account = Blockchain.GetConsensusAddress(Blockchain.StandbyValidators).ToArray(); - NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(50_000_008); + NativeContract.NEO.BalanceOf(snapshot, account).Should().Be(100_000_000); account[5]++; // Without existing balance @@ -276,53 +268,23 @@ public void TestGetNextBlockValidators2() } [TestMethod] - public void TestGetRegisteredValidators1() + public void TestGetCandidates1() { - using (ApplicationEngine engine = NativeContract.NEO.TestCall("getCandidates")) - { - var array = engine.ResultStack.Pop(); - array.Count.Should().Be(21); - ((VM.Types.Struct)array[0])[0].GetSpan().ToHexString().Should().Be("020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639"); - ((VM.Types.Struct)array[0])[1].GetInteger().Should().Be(new BigInteger(1785714)); - ((VM.Types.Struct)array[1])[0].GetSpan().ToHexString().Should().Be("0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30"); - ((VM.Types.Struct)array[1])[1].GetInteger().Should().Be(new BigInteger(1785714)); - ((VM.Types.Struct)array[2])[0].GetSpan().ToHexString().Should().Be("0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d"); - ((VM.Types.Struct)array[2])[1].GetInteger().Should().Be(new BigInteger(1785714)); - ((VM.Types.Struct)array[3])[0].GetSpan().ToHexString().Should().Be("023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe"); - ((VM.Types.Struct)array[3])[1].GetInteger().Should().Be(new BigInteger(1785714)); - ((VM.Types.Struct)array[4])[0].GetSpan().ToHexString().Should().Be("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70"); - ((VM.Types.Struct)array[4])[1].GetInteger().Should().Be(new BigInteger(3571428)); - ((VM.Types.Struct)array[5])[0].GetSpan().ToHexString().Should().Be("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d"); - ((VM.Types.Struct)array[5])[1].GetInteger().Should().Be(new BigInteger(3571428)); - ((VM.Types.Struct)array[6])[0].GetSpan().ToHexString().Should().Be("02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad"); - ((VM.Types.Struct)array[6])[1].GetInteger().Should().Be(new BigInteger(1785714)); - } + using ApplicationEngine engine = NativeContract.NEO.TestCall("getCandidates"); + var array = engine.ResultStack.Pop(); + array.Count.Should().Be(0); } [TestMethod] - public void TestGetRegisteredValidators2() + public void TestGetCandidates2() { var snapshot = Blockchain.Singleton.GetSnapshot(); - var result = NativeContract.NEO.GetCandidates(snapshot).ToArray(); - result.Length.Should().Be(21); - result[0].PublicKey.ToArray().ToHexString().Should().Be("020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639"); - result[0].Votes.Should().Be(new BigInteger(1785714)); - result[1].PublicKey.ToArray().ToHexString().Should().Be("0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30"); - result[1].Votes.Should().Be(new BigInteger(1785714)); - result[2].PublicKey.ToArray().ToHexString().Should().Be("0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d"); - result[2].Votes.Should().Be(new BigInteger(1785714)); - result[3].PublicKey.ToArray().ToHexString().Should().Be("023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe"); - result[3].Votes.Should().Be(new BigInteger(1785714)); - result[4].PublicKey.ToArray().ToHexString().Should().Be("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70"); - result[4].Votes.Should().Be(new BigInteger(3571428)); - result[5].PublicKey.ToArray().ToHexString().Should().Be("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d"); - result[5].Votes.Should().Be(new BigInteger(3571428)); - result[6].PublicKey.ToArray().ToHexString().Should().Be("02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad"); - result[6].Votes.Should().Be(new BigInteger(1785714)); + var result = NativeContract.NEO.GetCandidates(snapshot); + result.Length.Should().Be(0); StorageKey key = NativeContract.NEO.CreateStorageKey(33, ECCurve.Secp256r1.G); snapshot.Storages.Add(key, new StorageItem(new CandidateState())); - NativeContract.NEO.GetCandidates(snapshot).ToArray().Length.Should().Be(22); + NativeContract.NEO.GetCandidates(snapshot).Length.Should().Be(1); } [TestMethod]