Skip to content

Commit 1c8930c

Browse files
authored
Clearer RpcServer.GetCandinates to avoid false positives in static analysis. (#943)
Opimize: clearer implementation for RpcServer.GetCandinates
1 parent d91898c commit 1c8930c

File tree

2 files changed

+30
-26
lines changed

2 files changed

+30
-26
lines changed

plugins/RpcServer/RpcServer.Blockchain.cs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -572,48 +572,46 @@ protected internal virtual JToken GetCandidates()
572572
{
573573
script = sb.EmitDynamicCall(NativeContract.NEO.Hash, "getCandidates").ToArray();
574574
}
575-
StackItem[] resultstack;
575+
576+
StackItem[] resultStack;
576577
try
577578
{
578579
using var engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: settings.MaxGasInvoke);
579-
resultstack = engine.ResultStack.ToArray();
580+
resultStack = engine.ResultStack.ToArray();
580581
}
581582
catch
582583
{
583584
throw new RpcException(RpcError.InternalServerError.WithData("Can't get candidates."));
584585
}
585586

586-
JObject json = new();
587+
// GetCandidates should return a 1-element array.
588+
// If the behavior is unexpected, throw an exception(rather than returning an empty result), and the UT will find it.
589+
if (resultStack.Length != 1) // A empty array even if no candidate
590+
throw new RpcException(RpcError.InternalServerError.WithData("Unexpected GetCandidates result."));
591+
587592
try
588593
{
589-
if (resultstack.Length > 0)
590-
{
591-
JArray jArray = new();
592-
var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, system.Settings.ValidatorsCount)
593-
?? throw new RpcException(RpcError.InternalServerError.WithData("Can't get next block validators."));
594+
var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, system.Settings.ValidatorsCount)
595+
?? throw new RpcException(RpcError.InternalServerError.WithData("Can't get next block validators."));
594596

595-
foreach (var item in resultstack)
597+
var candidates = (Array)resultStack[0];
598+
var result = new JArray();
599+
foreach (Struct ele in candidates)
600+
{
601+
var publickey = ele[0].GetSpan().ToHexString();
602+
result.Add(new JObject()
596603
{
597-
var value = (Array)item;
598-
foreach (Struct ele in value)
599-
{
600-
var publickey = ele[0].GetSpan().ToHexString();
601-
json["publickey"] = publickey;
602-
json["votes"] = ele[1].GetInteger().ToString();
603-
json["active"] = validators.ToByteArray().ToHexString().Contains(publickey);
604-
jArray.Add(json);
605-
json = new();
606-
}
607-
return jArray;
608-
}
604+
["publickey"] = publickey,
605+
["votes"] = ele[1].GetInteger().ToString(),
606+
["active"] = validators.ToByteArray().ToHexString().Contains(publickey),
607+
});
609608
}
609+
return result;
610610
}
611611
catch
612612
{
613-
throw new RpcException(RpcError.InternalServerError.WithData("Can't get next block validators"));
613+
throw new RpcException(RpcError.InternalServerError.WithData("Can't get candidates."));
614614
}
615-
616-
return json;
617615
}
618616

619617
/// <summary>

tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,13 +594,19 @@ public void TestGetCandidates()
594594
var json = new JArray();
595595
var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, _neoSystem.Settings.ValidatorsCount);
596596

597-
var key = new KeyBuilder(NativeContract.NEO.Id, 33)
597+
var key1 = new KeyBuilder(NativeContract.NEO.Id, 33)
598598
.Add(ECPoint.Parse("02237309a0633ff930d51856db01d17c829a5b2e5cc2638e9c03b4cfa8e9c9f971", ECCurve.Secp256r1));
599-
snapshot.Add(key, new StorageItem(new CandidateState() { Registered = true, Votes = 10000 }));
599+
snapshot.Add(key1, new StorageItem(new CandidateState() { Registered = true, Votes = 10000 }));
600+
var key2 = new KeyBuilder(NativeContract.NEO.Id, 33)
601+
.Add(ECPoint.Parse("0285265dc8859d05e1e42a90d6c29a9de15531eac182489743e6a947817d2a9f66", ECCurve.Secp256r1));
602+
snapshot.Add(key2, new StorageItem(new CandidateState() { Registered = true, Votes = 10001 }));
600603
snapshot.Commit();
601604

602605
var candidates = NativeContract.NEO.GetCandidates(_neoSystem.GetSnapshotCache());
606+
Assert.AreEqual(2, candidates.Count());
607+
603608
var result = _rpcServer.GetCandidates();
609+
Assert.AreEqual(2, candidates.Count());
604610
foreach (var candidate in candidates)
605611
{
606612
var item = new JObject()

0 commit comments

Comments
 (0)