private static void CheckCandidate(StoreView snapshot, StorageKey key, CandidateState candidate) { if (!candidate.Registered && candidate.Votes.IsZero) { snapshot.Storages.Delete(key); } }
private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) { return(false); } StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); if (engine.Snapshot.Storages.TryGet(key) is null) { return(true); } StorageItem item = engine.Snapshot.Storages.GetAndChange(key); CandidateState state = item.GetInteroperable <CandidateState>(); if (state.Votes.IsZero) { engine.Snapshot.Storages.Delete(key); } else { state.Registered = false; } return(true); }
/// <summary> /// <para> /// Initializes a new instances of the <see cref="CandidateSet"/> class with the provided <paramref name="endpoints"/>, /// <paramref name="values"/>, and <paramref name="scores"/>. /// </para> /// <para> /// The constructor is provided to enable unit tests of implementations of <see cref="EndpointSelector"/> /// and <see cref="IEndpointSelectorPolicy"/>. /// </para> /// </summary> /// <param name="endpoints">The list of endpoints, sorted in descending priority order.</param> /// <param name="values">The list of <see cref="RouteValueDictionary"/> instances.</param> /// <param name="scores">The list of endpoint scores. <see cref="CandidateState.Score"/>.</param> public CandidateSet(Endpoint[] endpoints, RouteValueDictionary[] values, int[] scores) { if (endpoints == null) { throw new ArgumentNullException(nameof(endpoints)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (scores == null) { throw new ArgumentNullException(nameof(scores)); } if (endpoints.Length != values.Length || endpoints.Length != scores.Length) { throw new ArgumentException($"The provided {nameof(endpoints)}, {nameof(values)}, and {nameof(scores)} must have the same length."); } Candidates = new CandidateState[endpoints.Length]; for (var i = 0; i < endpoints.Length; i++) { Candidates[i] = new CandidateState(endpoints[i], values[i], scores[i]); } }
public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } // The goal of this method is to perform the final matching: // Map between route values matched by the template and the ones we want to expose to the action for binding. // (tweaking the route values is fine here) // Invalidating the candidate if the key/function values are not valid/missing. // Perform overload resolution for functions by looking at the candidates and their metadata. for (var i = 0; i < candidates.Count; i++) { ref CandidateState candidate = ref candidates[i]; if (!candidates.IsValidCandidate(i)) { continue; } IODataRoutingMetadata metadata = candidate.Endpoint.Metadata.OfType <IODataRoutingMetadata>().FirstOrDefault(); if (metadata == null) { continue; } IHttpMethodMetadata httpMetadata = candidate.Endpoint.Metadata.GetMetadata <IHttpMethodMetadata>(); if (httpMetadata == null) { // Check the http method if (metadata.HttpMethods != null && !metadata.HttpMethods.Contains(httpContext.Request.Method)) { candidates.SetValidity(i, false); continue; } } ODataTemplateTranslateContext translatorContext = new ODataTemplateTranslateContext(httpContext, candidate.Values, metadata.Model); try { ODataPath odataPath = _translator.Translate(metadata.Template, translatorContext); if (odataPath != null) { IODataFeature odataFeature = httpContext.ODataFeature(); odataFeature.PrefixName = metadata.Prefix; odataFeature.Model = metadata.Model; odataFeature.Path = odataPath; } else { candidates.SetValidity(i, false); } } catch (Exception) { candidates.SetValidity(i, false); } }
private void RegisterCandidateInternal(StoreView snapshot, ECPoint pubkey) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable <CandidateState>(); state.Registered = true; }
// Used in tests. internal CandidateSet(Candidate[] candidates) { Candidates = new CandidateState[candidates.Length]; for (var i = 0; i < candidates.Length; i++) { Candidates[i] = new CandidateState(candidates[i].Endpoint, candidates[i].Score); } }
private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) { return(false); } NeoAccountState state_account = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable <NeoAccountState>(); if (state_account is null) { return(false); } CandidateState validator_new = null; if (voteTo != null) { validator_new = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable <CandidateState>(); if (validator_new is null) { return(false); } if (!validator_new.Registered) { return(false); } } if (state_account.VoteTo is null ^ voteTo is null) { StorageItem item = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)); if (state_account.VoteTo is null) { item.Add(state_account.Balance); } else { item.Add(-state_account.Balance); } } if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable <CandidateState>(); state_validator.Votes -= state_account.Balance; if (!state_validator.Registered && state_validator.Votes.IsZero) { engine.Snapshot.Storages.Delete(key); } } state_account.VoteTo = voteTo; if (validator_new != null) { validator_new.Votes += state_account.Balance; } return(true); }
private async ContractTask <bool> Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) { return(false); } VauthAccountState state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable <VauthAccountState>(); if (state_account is null) { return(false); } CandidateState validator_new = null; if (voteTo != null) { validator_new = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable <CandidateState>(); if (validator_new is null) { return(false); } if (!validator_new.Registered) { return(false); } } if (state_account.VoteTo is null ^ voteTo is null) { StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)); if (state_account.VoteTo is null) { item.Add(state_account.Balance); } else { item.Add(-state_account.Balance); } } await DistributeValt(engine, account, state_account); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); StorageItem storage_validator = engine.Snapshot.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable <CandidateState>(); state_validator.Votes -= state_account.Balance; CheckCandidate(engine.Snapshot, state_account.VoteTo, state_validator); } state_account.VoteTo = voteTo; if (validator_new != null) { validator_new.Votes += state_account.Balance; } return(true); }
private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState candidate) { if (!candidate.Registered && candidate.Votes.IsZero) { foreach (var(rewardKey, _) in snapshot.Find(CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(pubkey).ToArray()).ToArray()) { snapshot.Delete(rewardKey); } snapshot.Delete(CreateStorageKey(Prefix_Candidate).Add(pubkey)); } }
private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) { return(false); } StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable <CandidateState>(); state.Registered = true; return(true); }
protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { DistributeGas(engine, account, state); if (amount.IsZero) { return; } if (state.VoteTo != null) { StorageItem storage_validator = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Candidate, state.VoteTo.ToArray())); CandidateState state_validator = storage_validator.GetInteroperable <CandidateState>(); state_validator.Votes += amount; } }
protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { DistributeGas(engine, account, state); if (amount.IsZero) { return; } if (state.VoteTo is null) { return; } engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); CandidateState candidate = engine.Snapshot.Storages.GetAndChange(key).GetInteroperable <CandidateState>(); candidate.Votes += amount; CheckCandidate(engine.Snapshot, key, candidate); }
internal override async ContractTask OnBalanceChanging(ApplicationEngine engine, UInt160 account, VauthAccountState state, BigInteger amount) { await DistributeValt(engine, account, state); if (amount.IsZero) { return; } if (state.VoteTo is null) { return; } engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); CandidateState candidate = engine.Snapshot.GetAndChange(key).GetInteroperable <CandidateState>(); candidate.Votes += amount; CheckCandidate(engine.Snapshot, state.VoteTo, candidate); }
private bool UnregisterCandidate(StoreView snapshot, ECPoint pubkey) { StorageKey key = CreateStorageKey(Prefix_Candidate, pubkey); if (snapshot.Storages.TryGet(key) is null) { return(true); } StorageItem item = snapshot.Storages.GetAndChange(key); CandidateState state = item.GetInteroperable <CandidateState>(); if (state.Votes.IsZero) { snapshot.Storages.Delete(key); } else { state.Registered = false; } return(true); }
private bool Vote(StoreView snapshot, UInt160 account, ECPoint voteTo) { StorageKey key_account = CreateAccountKey(account); if (snapshot.Storages.TryGet(key_account) is null) { return(false); } StorageItem storage_account = snapshot.Storages.GetAndChange(key_account); NeoAccountState state_account = storage_account.GetInteroperable <NeoAccountState>(); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate, state_account.VoteTo.ToArray()); StorageItem storage_validator = snapshot.Storages.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable <CandidateState>(); state_validator.Votes -= state_account.Balance; if (!state_validator.Registered && state_validator.Votes.IsZero) { snapshot.Storages.Delete(key); } } state_account.VoteTo = voteTo; if (voteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate, voteTo.ToArray()); if (snapshot.Storages.TryGet(key) is null) { return(false); } StorageItem storage_validator = snapshot.Storages.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable <CandidateState>(); if (!state_validator.Registered) { return(false); } state_validator.Votes += state_account.Balance; } return(true); }
internal void Select(HttpContext httpContext, CandidateSet candidateSet) { IODataFeature odataFeature = httpContext.ODataFeature(); ActionDescriptor actionDescriptor = odataFeature.ActionDescriptor; if (actionDescriptor != null) { int count = candidateSet.Count; for (int i = 0; i < count; i++) { CandidateState candidate = candidateSet[i]; ActionDescriptor action = candidate.Endpoint.Metadata.GetMetadata <ActionDescriptor>(); // Noted: we simple use the "ReferenceEquals" to compare the action descriptor. // So far, i don't know the risk, i need .NET team help me to verify it? if (object.ReferenceEquals(action, actionDescriptor)) { httpContext.SetEndpoint(candidate.Endpoint); httpContext.Request.RouteValues = candidate.Values; return; } } } }
internal override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { GasDistribution distribution = DistributeGas(engine, account, state); if (distribution is not null) { var list = engine.CurrentContext.GetState <List <GasDistribution> >(); list.Add(distribution); } if (amount.IsZero) { return; } if (state.VoteTo is null) { return; } engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); CandidateState candidate = engine.Snapshot.GetAndChange(key).GetInteroperable <CandidateState>(); candidate.Votes += amount; CheckCandidate(engine.Snapshot, state.VoteTo, candidate); }
/// <summary> /// Applies the policy to the CandidateSet. /// </summary> /// <param name="httpContext">The context associated with the current request.</param> /// <param name="candidates">The CandidateSet.</param> /// <returns>The task.</returns> public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates) { if (httpContext == null) { throw Error.ArgumentNull(nameof(httpContext)); } IODataFeature odataFeature = httpContext.ODataFeature(); if (odataFeature.Path != null) { // If we have the OData path setting, it means there's some Policy working. // Let's skip this default OData matcher policy. return(Task.CompletedTask); } // The goal of this method is to perform the final matching: // Map between route values matched by the template and the ones we want to expose to the action for binding. // (tweaking the route values is fine here) // Invalidating the candidate if the key/function values are not valid/missing. // Perform overload resolution for functions by looking at the candidates and their metadata. for (var i = 0; i < candidates.Count; i++) { ref CandidateState candidate = ref candidates[i]; if (!candidates.IsValidCandidate(i)) { continue; } IODataRoutingMetadata metadata = candidate.Endpoint.Metadata.OfType <IODataRoutingMetadata>().FirstOrDefault(); if (metadata == null) { continue; } if (odataFeature.Path != null) { // If it's odata endpoint, and we have a path set, let other odata endpoints invalid. candidates.SetValidity(i, false); continue; } ODataTemplateTranslateContext translatorContext = new ODataTemplateTranslateContext(httpContext, candidate.Endpoint, candidate.Values, metadata.Model); ODataPath odataPath = _translator.Translate(metadata.Template, translatorContext); if (odataPath != null) { odataFeature.RoutePrefix = metadata.Prefix; odataFeature.Model = metadata.Model; odataFeature.Path = odataPath; MergeRouteValues(translatorContext.UpdatedValues, candidate.Values); // Shall we break the remaining candidates? // So far the answer is no. Because we can use this matcher to obsolete the unmatched endpoint. // break; } else { candidates.SetValidity(i, false); } }
public void addVotesForCandidates(CandidateState cs) { Votes.Add(cs.ID, cs); TotalNumberOfVotes += cs.numberOfVotes; }
internal static bool IsValidCandidate(ref CandidateState candidate) { return(candidate.Score >= 0); }
public void Check_UnregisterCandidate() { var snapshot = Blockchain.Singleton.GetSnapshot(); var keyCount = snapshot.Storages.GetChangeSet().Count(); var point = Blockchain.StandbyValidators[0].EncodePoint(true); //without register var ret = Check_UnregisterCandidate(snapshot, point); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount); //register and then unregister ret = Check_RegisterValidator(snapshot, point); StorageItem item = snapshot.Storages.GetAndChange(CreateStorageKey(33, point)); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); var members = NativeContract.NEO.GetCandidates(snapshot); Assert.AreEqual(1, members.Length); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); StorageKey key = CreateStorageKey(33, point); snapshot.Storages.TryGet(key).Should().NotBeNull(); ret = Check_UnregisterCandidate(snapshot, point); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount); members = NativeContract.NEO.GetCandidates(snapshot); Assert.AreEqual(0, members.Length); snapshot.Storages.TryGet(key).Should().BeNull(); //register with votes, then unregister ret = Check_RegisterValidator(snapshot, point); var G_Account = Contract.CreateSignatureContract(ECCurve.Secp256r1.G).ScriptHash.ToArray(); snapshot.Storages.Add(CreateStorageKey(20, G_Account), new StorageItem(new NeoAccountState())); var accountState = snapshot.Storages.TryGet(CreateStorageKey(20, G_Account)).GetInteroperable <NeoAccountState>(); accountState.Balance = 100; Check_Vote(snapshot, G_Account, Blockchain.StandbyValidators[0].ToArray(), true); ret = Check_UnregisterCandidate(snapshot, point); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); snapshot.Storages.TryGet(key).Should().NotBeNull(); StorageItem pointItem = snapshot.Storages.TryGet(key); CandidateState pointState = pointItem.GetInteroperable <CandidateState>(); pointState.Registered.Should().BeFalse(); pointState.Votes.Should().Be(100); //vote fail ret = Check_Vote(snapshot, G_Account, Blockchain.StandbyValidators[0].ToArray(), true); ret.State.Should().BeTrue(); ret.Result.Should().BeFalse(); accountState.VoteTo.Should().Be(Blockchain.StandbyValidators[0]); }
public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } IODataFeature odataFeature = httpContext.ODataFeature(); if (odataFeature.Path != null) { // If we have the OData path setting, it means there's some Policy working. // Let's skip this default OData matcher policy. return(Task.CompletedTask); } for (var i = 0; i < candidates.Count; i++) { ref CandidateState candidate = ref candidates[i]; if (!candidates.IsValidCandidate(i)) { continue; } IODataRoutingMetadata metadata = candidate.Endpoint.Metadata.OfType <IODataRoutingMetadata>().FirstOrDefault(); if (metadata == null) { continue; } // Get api-version query from HttpRequest? QueryStringApiVersionReader reader = new QueryStringApiVersionReader("api-version"); string apiVersionStr = reader.Read(httpContext.Request); if (apiVersionStr == null) { candidates.SetValidity(i, false); continue; } ApiVersion apiVersion = ApiVersion.Parse(apiVersionStr); IEdmModel model = GetEdmModel(apiVersion); if (model == null) { candidates.SetValidity(i, false); continue; } if (!IsApiVersionMatch(candidate.Endpoint.Metadata, apiVersion)) { candidates.SetValidity(i, false); continue; } ODataTemplateTranslateContext translatorContext = new ODataTemplateTranslateContext(httpContext, candidate.Endpoint, candidate.Values, model); try { ODataPath odataPath = _translator.Translate(metadata.Template, translatorContext); if (odataPath != null) { odataFeature.RoutePrefix = metadata.Prefix; odataFeature.Model = model; odataFeature.Path = odataPath; ODataOptions options = new ODataOptions(); UpdateQuerySetting(options); options.AddRouteComponents(model); odataFeature.Services = options.GetRouteServices(string.Empty); MergeRouteValues(translatorContext.UpdatedValues, candidate.Values); } else { candidates.SetValidity(i, false); } } catch { candidates.SetValidity(i, false); } }