diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs
index 9aca67043d..a210df53b1 100644
--- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs
+++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs
@@ -20,6 +20,7 @@
using System.IO;
using System.Linq;
using System.Numerics;
+using System.Runtime.InteropServices;
using Array = Neo.VM.Types.Array;
namespace Neo.SmartContract
@@ -309,10 +310,39 @@ protected internal int GetInvocationCounter()
/// The next random number.
protected internal BigInteger GetRandom()
{
- byte[] buffer;
+ Span buffer;
// In the unit of datoshi, 1 datoshi = 1e-8 GAS
long price;
- if (IsHardforkEnabled(Hardfork.HF_Aspidochelone))
+ if (IsHardforkEnabled(Hardfork.HF_Faun))
+ {
+ buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network + random_times++);
+ var s0 = BitConverter.ToUInt64(buffer[0..8]);
+ var s1 = BitConverter.ToUInt64(buffer[8..16]);
+
+ buffer = Cryptography.Helper.Murmur128(buffer, ProtocolSettings.Network + random_times++);
+ var s2 = BitConverter.ToUInt64(buffer[0..8]);
+ var s3 = BitConverter.ToUInt64(buffer[8..16]);
+
+ // Update PRNG state.
+ ulong t = s1 << 17;
+ s2 ^= s0;
+ s3 ^= s1;
+ s1 ^= s2;
+ s0 ^= s3;
+ s2 ^= t;
+ s3 = BitOperations.RotateLeft(s3, 45);
+
+ buffer = new byte[32];
+ MemoryMarshal.Write(buffer[0..8], s0);
+ MemoryMarshal.Write(buffer[8..16], s1);
+ MemoryMarshal.Write(buffer[16..24], s2);
+ MemoryMarshal.Write(buffer[24..32], s3);
+
+ price = 1 << 13;
+ AddFee(price * ExecFeeFactor);
+ return new BigInteger(buffer, isUnsigned: true) % (BigInteger.One << 255) - BigInteger.One;
+ }
+ else if (IsHardforkEnabled(Hardfork.HF_Aspidochelone))
{
buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network + randomTimes++);
price = 1 << 13;
diff --git a/src/Neo/SmartContract/Native/StdLib.cs b/src/Neo/SmartContract/Native/StdLib.cs
index 326bb62f68..67955c4486 100644
--- a/src/Neo/SmartContract/Native/StdLib.cs
+++ b/src/Neo/SmartContract/Native/StdLib.cs
@@ -276,5 +276,34 @@ private static int StrLen([MaxLength(MaxInputLength)] string str)
return count;
}
+
+ [ContractMethod(Hardfork.HF_Faun, CpuFee = 1 << 13)]
+ private static BigInteger GetRandom(ApplicationEngine engine, BigInteger maxValue)
+ {
+ if (maxValue.Sign < 0)
+ throw new ArgumentOutOfRangeException(nameof(maxValue));
+
+ if (maxValue <= BigInteger.One)
+ return BigInteger.Zero;
+
+ var maxValueBits = maxValue.GetByteCount() * 8;
+ var maxMaxValue = BigInteger.One << maxValueBits;
+
+ var randomProduct = maxValue * (engine.GetRandom() % maxMaxValue);
+ var lowPart = randomProduct % maxMaxValue;
+
+ if (lowPart < maxValue)
+ {
+ var threshold = (maxMaxValue - maxValue) % maxValue;
+
+ while (lowPart < threshold)
+ {
+ randomProduct = maxValue * (engine.GetRandom() % maxMaxValue);
+ lowPart = randomProduct % maxMaxValue;
+ }
+ }
+
+ return randomProduct >> maxValueBits;
+ }
}
}
diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs
index 9297af0951..144f590941 100644
--- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs
+++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs
@@ -42,7 +42,7 @@ public void TestSetup()
_nativeStates = new Dictionary
{
{"ContractManagement", """{"id":-1,"updatecounter":0,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":3581846399},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getContractById","parameters":[{"name":"id","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getContractHashes","parameters":[],"returntype":"InteropInterface","offset":35,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"hasMethod","parameters":[{"name":"hash","type":"Hash160"},{"name":"method","type":"String"},{"name":"pcount","type":"Integer"}],"returntype":"Boolean","offset":49,"safe":true},{"name":"isContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Boolean","offset":56,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":63,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":70,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":77,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}""" },
- {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQA==","checksum":2426471238},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"String","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"String"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"hexDecode","parameters":[{"name":"str","type":"String"}],"returntype":"ByteArray","offset":77,"safe":true},{"name":"hexEncode","parameters":[{"name":"bytes","type":"ByteArray"}],"returntype":"String","offset":84,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":91,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":98,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":105,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":112,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":126,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":133,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":140,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":147,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":154,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":161,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":168,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
+ {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2703728828},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"String","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"String"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"getRandom","parameters":[{"name":"maxValue","type":"Integer"}],"returntype":"Integer","offset":77,"safe":true},{"name":"hexDecode","parameters":[{"name":"str","type":"String"}],"returntype":"ByteArray","offset":84,"safe":true},{"name":"hexEncode","parameters":[{"name":"bytes","type":"ByteArray"}],"returntype":"String","offset":91,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":98,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":105,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":112,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":119,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":126,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":133,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":140,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":147,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":154,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":161,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":168,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":175,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQA==","checksum":174904780},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"recoverSecp256K1","parameters":[{"name":"messageHash","type":"ByteArray"},{"name":"signature","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":70,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":77,"safe":true},{"name":"verifyWithEd25519","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"}],"returntype":"Boolean","offset":84,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17","NEP-27"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":77,"safe":false},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":84,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":98,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":105,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":112,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":119,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":126,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":140,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs
index 5e9040a5de..62e0eb87de 100644
--- a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs
+++ b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs
@@ -10,6 +10,7 @@
// modifications are permitted.
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Builders;
using Neo.Extensions;
using Neo.SmartContract;
using Neo.SmartContract.Native;
@@ -455,6 +456,92 @@ public void TestHexEncodeDecode()
}
[TestMethod]
+ public void TestGetRandomRanges()
+ {
+ var snapshotCache = TestBlockchain.GetTestSnapshotCache();
+
+ using (var script = new ScriptBuilder())
+ {
+ // Test encoding
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", (BigInteger.One << 255) - BigInteger.One);
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", (BigInteger.One << 127) - BigInteger.One);
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", (BigInteger.One << 63) - BigInteger.One);
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", (BigInteger.One << 31) - BigInteger.One);
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", (BigInteger.One << 15) - BigInteger.One);
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", (BigInteger.One << 7) - BigInteger.One);
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", BigInteger.Zero);
+
+ var tx = TransactionBuilder.CreateEmpty()
+ .Nonce((uint)Random.Shared.Next())
+ .Build();
+
+ using var engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshotCache, settings: TestProtocolSettings.Default, gas: long.MaxValue);
+ engine.LoadScript(script.ToArray());
+
+ Assert.AreEqual(VMState.HALT, engine.Execute());
+ Assert.AreEqual(7, engine.ResultStack.Count);
+
+ var actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue <= 0);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+
+ actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < (BigInteger.One << 7) - BigInteger.One);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+
+ actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < (BigInteger.One << 15) - BigInteger.One);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+
+ actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < (BigInteger.One << 31) - BigInteger.One);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+
+ actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < (BigInteger.One << 63) - BigInteger.One);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+
+ actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < (BigInteger.One << 127) - BigInteger.One);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+
+ actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < (BigInteger.One << 255) - BigInteger.One);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+ }
+ }
+
+
+ [TestMethod]
+ public void TestGetRandomRanges2()
+ {
+ var snapshotCache = TestBlockchain.GetTestSnapshotCache();
+
+ using (var script = new ScriptBuilder())
+ {
+ // Test encoding
+ for (var i = 0; i < 2000; i++)
+ script.EmitDynamicCall(NativeContract.StdLib.Hash, "getRandom", 10);
+
+ var tx = TransactionBuilder.CreateEmpty()
+ .Nonce((uint)Random.Shared.Next())
+ .Build();
+
+ using var engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshotCache, settings: TestProtocolSettings.Default, gas: long.MaxValue);
+ engine.LoadScript(script.ToArray());
+
+ Assert.AreEqual(VMState.HALT, engine.Execute());
+ Assert.AreEqual(2000, engine.ResultStack.Count);
+
+ for (var i = 0; i < engine.ResultStack.Count; i++)
+ {
+ var actualValue = engine.ResultStack.Pop().GetInteger();
+ Assert.IsTrue(actualValue < 10);
+ Assert.IsTrue(actualValue >= BigInteger.Zero);
+ }
+ }
+ }
+
public void TestMemorySearch()
{
var snapshotCache = TestBlockchain.GetTestSnapshotCache();
diff --git a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs
index 7c619ff564..b64de255a5 100644
--- a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs
+++ b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs
@@ -118,11 +118,13 @@ public void TestGetRandomSameBlock()
var rand_9 = engine_2.GetRandom();
var rand_10 = engine_2.GetRandom();
- Assert.AreEqual(BigInteger.Parse("271339657438512451304577787170704246350"), rand_1);
- Assert.AreEqual(BigInteger.Parse("98548189559099075644778613728143131367"), rand_2);
- Assert.AreEqual(BigInteger.Parse("247654688993873392544380234598471205121"), rand_3);
- Assert.AreEqual(BigInteger.Parse("291082758879475329976578097236212073607"), rand_4);
- Assert.AreEqual(BigInteger.Parse("247152297361212656635216876565962360375"), rand_5);
+ var actualValue0 = (BigInteger.One << 255) - BigInteger.One;
+
+ Assert.IsTrue(rand_1 < actualValue0);
+ Assert.IsTrue(rand_2 < actualValue0);
+ Assert.IsTrue(rand_3 < actualValue0);
+ Assert.IsTrue(rand_4 < actualValue0);
+ Assert.IsTrue(rand_5 < actualValue0);
Assert.AreEqual(rand_6, rand_1);
Assert.AreEqual(rand_7, rand_2);
@@ -165,11 +167,13 @@ public void TestGetRandomDifferentBlock()
var rand_9 = engine_2.GetRandom();
var rand_10 = engine_2.GetRandom();
- Assert.AreEqual(BigInteger.Parse("271339657438512451304577787170704246350"), rand_1);
- Assert.AreEqual(BigInteger.Parse("98548189559099075644778613728143131367"), rand_2);
- Assert.AreEqual(BigInteger.Parse("247654688993873392544380234598471205121"), rand_3);
- Assert.AreEqual(BigInteger.Parse("291082758879475329976578097236212073607"), rand_4);
- Assert.AreEqual(BigInteger.Parse("247152297361212656635216876565962360375"), rand_5);
+ var actualValue0 = (BigInteger.One << 255) - BigInteger.One;
+
+ Assert.IsTrue(rand_1 < actualValue0);
+ Assert.IsTrue(rand_2 < actualValue0);
+ Assert.IsTrue(rand_3 < actualValue0);
+ Assert.IsTrue(rand_4 < actualValue0);
+ Assert.IsTrue(rand_5 < actualValue0);
Assert.AreNotEqual(rand_6, rand_1);
Assert.AreNotEqual(rand_7, rand_2);