diff --git a/src/neo/SmartContract/Native/NeoToken.cs b/src/neo/SmartContract/Native/NeoToken.cs index 32c10a18ac..3ec0b35958 100644 --- a/src/neo/SmartContract/Native/NeoToken.cs +++ b/src/neo/SmartContract/Native/NeoToken.cs @@ -348,6 +348,18 @@ public ECPoint[] GetCommittee(DataCache snapshot) return GetCommitteeFromCache(snapshot).Select(p => p.PublicKey).OrderBy(p => p).ToArray(); } + /// + /// Get account state. + /// + /// The snapshot used to read data. + /// account + /// The state of the account. + [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] + public NeoAccountState GetAccountState(DataCache snapshot, UInt160 account) + { + return snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); + } + /// /// Gets the address of the committee. /// diff --git a/src/neo/SmartContract/Native/StdLib.cs b/src/neo/SmartContract/Native/StdLib.cs index 101c1deebd..a3d9238b99 100644 --- a/src/neo/SmartContract/Native/StdLib.cs +++ b/src/neo/SmartContract/Native/StdLib.cs @@ -142,6 +142,28 @@ public static byte[] Base58Decode([MaxLength(MaxInputLength)] string s) return Base58.Decode(s); } + /// + /// Converts a byte array to its equivalent representation that is encoded with base-58 digits. The encoded contains the checksum of the binary data. + /// + /// The byte array to be encoded. + /// The encoded . + [ContractMethod(CpuFee = 1 << 16)] + public static string Base58CheckEncode([MaxLength(MaxInputLength)] byte[] data) + { + return Base58.Base58CheckEncode(data); + } + + /// + /// Converts the specified , which encodes binary data as base-58 digits, to an equivalent byte array. The encoded contains the checksum of the binary data. + /// + /// The base58 . + /// The decoded byte array. + [ContractMethod(CpuFee = 1 << 16)] + public static byte[] Base58CheckDecode([MaxLength(MaxInputLength)] string s) + { + return Base58.Base58CheckDecode(s); + } + [ContractMethod(CpuFee = 1 << 5)] private static int MemoryCompare([MaxLength(MaxInputLength)] byte[] str1, [MaxLength(MaxInputLength)] byte[] str2) { diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index e82346f782..da28b8d4e7 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -4,7 +4,7 @@ 2015-2021 The Neo Project Neo 3.0.0 - rc2 + rc3 The Neo Project net5.0 true @@ -26,11 +26,11 @@ - + - - + + diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index 3789cc02ff..d80cb735c5 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -375,6 +375,12 @@ public void Check_Transfer() NativeContract.NEO.BalanceOf(snapshot, from).Should().Be(99999999); NativeContract.NEO.BalanceOf(snapshot, to).Should().Be(1); + var (from_balance, _, _) = GetAccountState(snapshot, new UInt160(from)); + var (to_balance, _, _) = GetAccountState(snapshot, new UInt160(to)); + + from_balance.Should().Be(99999999); + to_balance.Should().Be(1); + // Check unclaim unclaim = Check_UnclaimedGas(snapshot, from, persistingBlock); @@ -853,6 +859,9 @@ public void TestVote() ret.State.Should().BeTrue(); ret.Result.Should().BeFalse(); + var (_, _, vote_to_null) = GetAccountState(snapshot, account); + vote_to_null.Should().BeNull(); + snapshot.Delete(keyAccount); snapshot.GetAndChange(keyAccount, () => new StorageItem(new NeoAccountState { @@ -862,6 +871,9 @@ public void TestVote() ret = Check_Vote(snapshot, account.ToArray(), ECCurve.Secp256r1.G.ToArray(), true, _persistingBlock); ret.State.Should().BeTrue(); ret.Result.Should().BeTrue(); + + var (_, _, voteto) = GetAccountState(snapshot, account); + voteto.ToHexString().Should().Be(ECCurve.Secp256r1.G.ToArray().ToHexString()); } internal (bool State, bool Result) Transfer4TesingOnBalanceChanging(BigInteger amount, bool addVotes) @@ -1080,5 +1092,25 @@ internal static (bool State, bool Result) Check_UnregisterCandidate(DataCache sn return (true, result.GetBoolean()); } + + internal static (BigInteger balance, BigInteger height, byte[] voteto) GetAccountState(DataCache snapshot, UInt160 account) + { + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); + + using var script = new ScriptBuilder(); + script.EmitDynamicCall(NativeContract.NEO.Hash, "getAccountState", account); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Struct)); + + VM.Types.Struct state = (result as VM.Types.Struct); + var balance = state[0].GetInteger(); + var height = state[1].GetInteger(); + var voteto = state[2].IsNull ? null : state[2].GetSpan().ToArray(); + return (balance, height, voteto); + } } } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_StdLib.cs b/tests/neo.UnitTests/SmartContract/Native/UT_StdLib.cs index 787faed9b9..8879c828b5 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_StdLib.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_StdLib.cs @@ -69,6 +69,60 @@ public void MemoryCompare() } } + [TestMethod] + public void CheckDecodeEncode() + { + var snapshot = TestBlockchain.GetTestSnapshot(); + + using (ScriptBuilder script = new()) + { + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base58CheckEncode", new byte[] { 1, 2, 3 }); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(1, engine.ResultStack.Count); + + Assert.AreEqual("3DUz7ncyT", engine.ResultStack.Pop().GetString()); + } + + using (ScriptBuilder script = new()) + { + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base58CheckDecode", "3DUz7ncyT"); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(1, engine.ResultStack.Count); + + CollectionAssert.AreEqual(new byte[] { 1, 2, 3 }, engine.ResultStack.Pop().GetSpan().ToArray()); + } + + // Error + + using (ScriptBuilder script = new()) + { + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base58CheckDecode", "AA"); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + } + + using (ScriptBuilder script = new()) + { + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base58CheckDecode", null); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + } + } + [TestMethod] public void MemorySearch() { diff --git a/tests/neo.UnitTests/neo.UnitTests.csproj b/tests/neo.UnitTests/neo.UnitTests.csproj index 944d1c82ba..95623808df 100644 --- a/tests/neo.UnitTests/neo.UnitTests.csproj +++ b/tests/neo.UnitTests/neo.UnitTests.csproj @@ -9,8 +9,8 @@ - - + +