diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3dae25a1df..dca46dbbd6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,12 +7,30 @@ on: env: DOTNET_VERSION: 8.0.x - COVERALL_COLLECT_OUTPUT: "/p:CollectCoverage=true /p:CoverletOutput='${{ github.workspace }}/TestResults/coverage/'" - COVERALL_MERGE_PATH: "/p:MergeWith='${{ github.workspace }}/TestResults/coverage/coverage.json'" jobs: + Format: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Check Format (*.cs) + run: dotnet format --verify-no-changes --verbosity diagnostic + + - name: Build (Neo.CLI) + run: | + dotnet build ./src/Neo.CLI \ + --output ./out/Neo.CLI + Test: + needs: [Format] timeout-minutes: 15 strategy: matrix: @@ -25,14 +43,6 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ env.DOTNET_VERSION }} - - name: Check format - if: matrix.os == 'ubuntu-latest' - run: | - dotnet format --verify-no-changes --verbosity diagnostic - - name: Build CLI - if: matrix.os == 'ubuntu-latest' - run: | - dotnet publish ./src/Neo.CLI - name: Test if: matrix.os != 'ubuntu-latest' run: | @@ -42,31 +52,40 @@ jobs: if: matrix.os == 'ubuntu-latest' run: | sudo apt-get --assume-yes install libleveldb-dev librocksdb-dev - - dotnet test ./tests/Neo.Cryptography.BLS12_381.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} - dotnet test ./tests/Neo.ConsoleService.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.UnitTests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.VM.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.Json.UnitTests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} + + dotnet test ./tests/Neo.Cryptography.BLS12_381.Tests --output ./bin/tests/Neo.Cryptography.BLS12_381.Tests + dotnet test ./tests/Neo.ConsoleService.Tests --output ./bin/tests/Neo.ConsoleService.Tests + dotnet test ./tests/Neo.UnitTests --output ./bin/tests/Neo.UnitTests + dotnet test ./tests/Neo.VM.Tests --output ./bin/tests/Neo.VM.Tests + dotnet test ./tests/Neo.Json.UnitTests --output ./bin/tests/Neo.Json.UnitTests # Plugins - dotnet test ./tests/Neo.Cryptography.MPTTrie.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.Network.RPC.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.Plugins.OracleService.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.Plugins.RpcServer.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} - dotnet test ./tests/Neo.Plugins.Storage.Tests ${{ env.COVERALL_COLLECT_OUTPUT }} ${{ env.COVERALL_MERGE_PATH }} /p:CoverletOutputFormat='cobertura' + dotnet test ./tests/Neo.Cryptography.MPTTrie.Tests --output ./bin/tests/Neo.Cryptography.MPTTrie.Tests + dotnet test ./tests/Neo.Network.RPC.Tests --output ./bin/tests/Neo.Network.RPC.Tests + dotnet test ./tests/Neo.Plugins.OracleService.Tests --output ./bin/tests/Neo.Plugins.OracleService.Tests + dotnet test ./tests/Neo.Plugins.RpcServer.Tests --output ./bin/tests/Neo.Plugins.RpcServer.Tests + dotnet test ./tests/Neo.Plugins.Storage.Tests --output ./bin/tests/Neo.Plugins.Storage.Tests - name: Coveralls if: matrix.os == 'ubuntu-latest' uses: coverallsapp/github-action@v2.3.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} - format: cobertura - file: ${{ github.workspace }}/TestResults/coverage/coverage.cobertura.xml + files: + ${{ github.workspace }}/tests/Neo.Cryptography.BLS12_381.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.ConsoleService.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.UnitTests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.VM.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.Json.UnitTests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.Cryptography.MPTTrie.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.Network.RPC.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.Plugins.OracleService.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.Plugins.RpcServer.Tests/TestResults/coverage.info + ${{ github.workspace }}/tests/Neo.Plugins.Storage.Tests/TestResults/coverage.info PublishPackage: if: github.ref == 'refs/heads/master' && startsWith(github.repository, 'neo-project/') - needs: Test + needs: [Test] runs-on: ubuntu-latest steps: - name: Checkout @@ -115,7 +134,7 @@ jobs: Release: if: github.ref == 'refs/heads/master' && startsWith(github.repository, 'neo-project/') - needs: Test + needs: [Test] runs-on: ubuntu-latest steps: - name: Checkout diff --git a/neo.sln b/neo.sln index 46ff7c64e8..b0de1c27b1 100644 --- a/neo.sln +++ b/neo.sln @@ -70,8 +70,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RpcServer", "src\Plugins\Rp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLiteWallet", "src\Plugins\SQLiteWallet\SQLiteWallet.csproj", "{F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StatesDumper", "src\Plugins\StatesDumper\StatesDumper.csproj", "{90CCA7D4-C277-4112-A036-BBB90C3FE3BE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StateService", "src\Plugins\StateService\StateService.csproj", "{88975A8D-4797-45A4-BC3E-15962A425A54}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StorageDumper", "src\Plugins\StorageDumper\StorageDumper.csproj", "{FF76D8A4-356B-461A-8471-BC1B83E57BBC}" @@ -202,10 +200,6 @@ Global {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|Any CPU.Build.0 = Debug|Any CPU {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|Any CPU.ActiveCfg = Release|Any CPU {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|Any CPU.Build.0 = Release|Any CPU - {90CCA7D4-C277-4112-A036-BBB90C3FE3BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {90CCA7D4-C277-4112-A036-BBB90C3FE3BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {90CCA7D4-C277-4112-A036-BBB90C3FE3BE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {90CCA7D4-C277-4112-A036-BBB90C3FE3BE}.Release|Any CPU.Build.0 = Release|Any CPU {88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|Any CPU.Build.0 = Debug|Any CPU {88975A8D-4797-45A4-BC3E-15962A425A54}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -257,7 +251,6 @@ Global {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B} = {C2DC830A-327A-42A7-807D-295216D30DBB} {A3941551-E72C-42D7-8C4D-5122CB60D73D} = {C2DC830A-327A-42A7-807D-295216D30DBB} {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1} = {C2DC830A-327A-42A7-807D-295216D30DBB} - {90CCA7D4-C277-4112-A036-BBB90C3FE3BE} = {C2DC830A-327A-42A7-807D-295216D30DBB} {88975A8D-4797-45A4-BC3E-15962A425A54} = {C2DC830A-327A-42A7-807D-295216D30DBB} {FF76D8A4-356B-461A-8471-BC1B83E57BBC} = {C2DC830A-327A-42A7-807D-295216D30DBB} {5E4947F3-05D3-4806-B0F3-30DAC71B5986} = {C2DC830A-327A-42A7-807D-295216D30DBB} diff --git a/src/Neo.CLI/CLI/MainService.Blockchain.cs b/src/Neo.CLI/CLI/MainService.Blockchain.cs index 9f5d40daa7..8a32eb8023 100644 --- a/src/Neo.CLI/CLI/MainService.Blockchain.cs +++ b/src/Neo.CLI/CLI/MainService.Blockchain.cs @@ -137,9 +137,9 @@ public void OnShowTransactionCommand(UInt256 hash) ConsoleHelper.Info("", " Nonce: ", $"{tx.Transaction.Nonce}"); ConsoleHelper.Info("", " Sender: ", $"{tx.Transaction.Sender}"); ConsoleHelper.Info("", " ValidUntilBlock: ", $"{tx.Transaction.ValidUntilBlock}"); - ConsoleHelper.Info("", " FeePerByte: ", $"{tx.Transaction.FeePerByte}"); - ConsoleHelper.Info("", " NetworkFee: ", $"{tx.Transaction.NetworkFee}"); - ConsoleHelper.Info("", " SystemFee: ", $"{tx.Transaction.SystemFee}"); + ConsoleHelper.Info("", " FeePerByte: ", $"{tx.Transaction.FeePerByte} datoshi"); + ConsoleHelper.Info("", " NetworkFee: ", $"{tx.Transaction.NetworkFee} datoshi"); + ConsoleHelper.Info("", " SystemFee: ", $"{tx.Transaction.SystemFee} datoshi"); ConsoleHelper.Info("", " Script: ", $"{Convert.ToBase64String(tx.Transaction.Script.Span)}"); ConsoleHelper.Info("", " Version: ", $"{tx.Transaction.Version}"); ConsoleHelper.Info("", " BlockIndex: ", $"{block.Index}"); diff --git a/src/Neo.CLI/CLI/MainService.Contracts.cs b/src/Neo.CLI/CLI/MainService.Contracts.cs index 94fbe32f89..684b3330bc 100644 --- a/src/Neo.CLI/CLI/MainService.Contracts.cs +++ b/src/Neo.CLI/CLI/MainService.Contracts.cs @@ -46,8 +46,8 @@ private void OnDeployCommand(string filePath, string? manifestPath = null, JObje UInt160 hash = SmartContract.Helper.GetContractHash(tx.Sender, nef.CheckSum, manifest.Name); ConsoleHelper.Info("Contract hash: ", $"{hash}"); - ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}"); - ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}"); + ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)} GAS"); + ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)} GAS"); ConsoleHelper.Info("Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); if (!ConsoleHelper.ReadUserInput("Relay tx? (no|yes)").IsYes()) // Add this in case just want to get hash but not relay { @@ -108,8 +108,8 @@ private void OnUpdateCommand(UInt160 scriptHash, string filePath, string manifes { ConsoleHelper.Info("Contract hash: ", $"{scriptHash}"); ConsoleHelper.Info("Updated times: ", $"{contract.UpdateCounter}"); - ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}"); - ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}"); + ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)} GAS"); + ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)} GAS"); ConsoleHelper.Info("Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); if (!ConsoleHelper.ReadUserInput("Relay tx? (no|yes)").IsYes()) // Add this in case just want to get hash but not relay { @@ -127,11 +127,12 @@ private void OnUpdateCommand(UInt160 scriptHash, string filePath, string manifes /// Contract parameters /// Transaction's sender /// Signer's accounts - /// Max fee for running the script + /// Max fee for running the script, in the unit of GAS [ConsoleCommand("invoke", Category = "Contract Commands")] private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray? contractParameters = null, UInt160? sender = null, UInt160[]? signerAccounts = null, decimal maxGas = 20) { - var gas = new BigDecimal(maxGas, NativeContract.GAS.Decimals); + // In the unit of datoshi, 1 datoshi = 1e-8 GAS + var datoshi = new BigDecimal(maxGas, NativeContract.GAS.Decimals); Signer[] signers = Array.Empty(); if (!NoWallet()) { @@ -163,12 +164,12 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray? contr Witnesses = Array.Empty(), }; - if (!OnInvokeWithResult(scriptHash, operation, out _, tx, contractParameters, gas: (long)gas.Value)) return; + if (!OnInvokeWithResult(scriptHash, operation, out _, tx, contractParameters, datoshi: (long)datoshi.Value)) return; if (NoWallet()) return; try { - tx = CurrentWallet!.MakeTransaction(NeoSystem.StoreView, tx.Script, sender, signers, maxGas: (long)gas.Value); + tx = CurrentWallet!.MakeTransaction(NeoSystem.StoreView, tx.Script, sender, signers, maxGas: (long)datoshi.Value); } catch (InvalidOperationException e) { @@ -176,7 +177,7 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray? contr return; } ConsoleHelper.Info("Network fee: ", - $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}\t", + $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)} GAS\t", "Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); if (!ConsoleHelper.ReadUserInput("Relay tx? (no|yes)").IsYes()) diff --git a/src/Neo.CLI/CLI/MainService.Plugins.cs b/src/Neo.CLI/CLI/MainService.Plugins.cs index 5b346fc33c..a73cdcb31e 100644 --- a/src/Neo.CLI/CLI/MainService.Plugins.cs +++ b/src/Neo.CLI/CLI/MainService.Plugins.cs @@ -228,24 +228,28 @@ private void OnPluginsCommand() { try { - var plugins = GetPluginListAsync().GetAwaiter().GetResult(); - if (plugins == null) return; - plugins - .Order() - .ForEach(f => + var plugins = GetPluginListAsync().GetAwaiter().GetResult()?.ToArray() ?? []; + var installedPlugins = Plugin.Plugins.ToList(); + + var maxLength = installedPlugins.Count == 0 ? 0 : installedPlugins.Max(s => s.Name.Length); + if (plugins.Length > 0) { - var installedPlugin = Plugin.Plugins.SingleOrDefault(pp => string.Equals(pp.Name, f, StringComparison.CurrentCultureIgnoreCase)); - if (installedPlugin != null) + maxLength = Math.Max(maxLength, plugins.Max(s => s.Length)); + } + + plugins.Select(s => (name: s, installedPlugin: Plugin.Plugins.SingleOrDefault(pp => string.Equals(pp.Name, s, StringComparison.InvariantCultureIgnoreCase)))) + .Concat(installedPlugins.Select(u => (name: u.Name, installedPlugin: (Plugin?)u)).Where(u => !plugins.Contains(u.name, StringComparer.InvariantCultureIgnoreCase))) + .OrderBy(u => u.name) + .ForEach((f) => { - var maxLength = plugins.Select(s => s.Length).OrderDescending().First(); - string tabs = string.Empty; - if (f.Length < maxLength) - tabs = "\t"; - ConsoleHelper.Info("", $"[Installed]\t {f,6}{tabs}", " @", $"{installedPlugin.Version.ToString(3)} {installedPlugin.Description}"); - } - else - ConsoleHelper.Info($"[Not Installed]\t {f}"); - }); + if (f.installedPlugin != null) + { + var tabs = f.name.Length < maxLength ? "\t" : string.Empty; + ConsoleHelper.Info("", $"[Installed]\t {f.name,6}{tabs}", " @", $"{f.installedPlugin.Version.ToString(3)} {f.installedPlugin.Description}"); + } + else + ConsoleHelper.Info($"[Not Installed]\t {f.name}"); + }); } catch (Exception ex) { diff --git a/src/Neo.CLI/CLI/MainService.Wallet.cs b/src/Neo.CLI/CLI/MainService.Wallet.cs index 4f65390f85..db33e89564 100644 --- a/src/Neo.CLI/CLI/MainService.Wallet.cs +++ b/src/Neo.CLI/CLI/MainService.Wallet.cs @@ -626,7 +626,7 @@ private void OnCancelCommand(UInt256 txid, UInt160? sender = null, UInt160[]? si { var snapshot = NeoSystem.StoreView; AssetDescriptor descriptor = new(snapshot, NeoSystem.Settings, NativeContract.GAS.Hash); - string extracFee = ConsoleHelper.ReadUserInput("This tx is not in mempool, please input extra fee manually"); + string extracFee = ConsoleHelper.ReadUserInput("This tx is not in mempool, please input extra fee (datoshi) manually"); if (!BigDecimal.TryParse(extracFee, descriptor.Decimals, out BigDecimal decimalExtraFee) || decimalExtraFee.Sign <= 0) { ConsoleHelper.Error("Incorrect Amount Format"); @@ -636,7 +636,7 @@ private void OnCancelCommand(UInt256 txid, UInt160? sender = null, UInt160[]? si }; ConsoleHelper.Info("Network fee: ", - $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}\t", + $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)} GAS\t", "Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); if (!ConsoleHelper.ReadUserInput("Relay tx? (no|yes)").IsYes()) diff --git a/src/Neo.CLI/CLI/MainService.cs b/src/Neo.CLI/CLI/MainService.cs index efe48b0165..7e96af9e85 100644 --- a/src/Neo.CLI/CLI/MainService.cs +++ b/src/Neo.CLI/CLI/MainService.cs @@ -375,7 +375,18 @@ public async void Start(CommandLineOptions options) ProtocolSettings protocol = ProtocolSettings.Load("config.json"); CustomProtocolSettings(options, protocol); CustomApplicationSettings(options, Settings.Default); - NeoSystem = new NeoSystem(protocol, Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8"))); + try + { + NeoSystem = new NeoSystem(protocol, Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8"))); + } + catch (DllNotFoundException) + { + ConsoleHelper.Error("DLL not found, please install Microsoft Visual C++ Redistributable." + Environment.NewLine + + "See https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist" + Environment.NewLine + + "Press any key to exit."); + Console.ReadKey(); + Environment.Exit(-1); + } NeoSystem.AddService(this); LocalNode = NeoSystem.LocalNode.Ask(new LocalNode.GetInstance()).Result; @@ -515,8 +526,8 @@ private static void WriteLineWithoutFlicker(string message = "", int maxWidth = /// /// script /// sender - /// Max fee for running the script - private void SendTransaction(byte[] script, UInt160? account = null, long gas = TestModeGas) + /// Max fee for running the script, in the unit of datoshi, 1 datoshi = 1e-8 GAS + private void SendTransaction(byte[] script, UInt160? account = null, long datoshi = TestModeGas) { if (NoWallet()) return; @@ -533,10 +544,10 @@ private void SendTransaction(byte[] script, UInt160? account = null, long gas = try { - Transaction tx = CurrentWallet!.MakeTransaction(snapshot, script, account, signers, maxGas: gas); + Transaction tx = CurrentWallet!.MakeTransaction(snapshot, script, account, signers, maxGas: datoshi); ConsoleHelper.Info("Invoking script with: ", $"'{Convert.ToBase64String(tx.Script.Span)}'"); - using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, snapshot, container: tx, settings: NeoSystem.Settings, gas: gas)) + using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, snapshot, container: tx, settings: NeoSystem.Settings, gas: datoshi)) { PrintExecutionOutput(engine, true); if (engine.State == VMState.FAULT) return; @@ -564,9 +575,9 @@ private void SendTransaction(byte[] script, UInt160? account = null, long gas = /// Transaction /// Contract parameters /// Show result stack if it is true - /// Max fee for running the script + /// Max fee for running the script, in the unit of datoshi, 1 datoshi = 1e-8 GAS /// Return true if it was successful - private bool OnInvokeWithResult(UInt160 scriptHash, string operation, out StackItem result, IVerifiable? verifiable = null, JArray? contractParameters = null, bool showStack = true, long gas = TestModeGas) + private bool OnInvokeWithResult(UInt160 scriptHash, string operation, out StackItem result, IVerifiable? verifiable = null, JArray? contractParameters = null, bool showStack = true, long datoshi = TestModeGas) { List parameters = new(); @@ -612,7 +623,7 @@ private bool OnInvokeWithResult(UInt160 scriptHash, string operation, out StackI tx.Script = script; } - using ApplicationEngine engine = ApplicationEngine.Run(script, NeoSystem.StoreView, container: verifiable, settings: NeoSystem.Settings, gas: gas); + using ApplicationEngine engine = ApplicationEngine.Run(script, NeoSystem.StoreView, container: verifiable, settings: NeoSystem.Settings, gas: datoshi); PrintExecutionOutput(engine, showStack); result = engine.State == VMState.FAULT ? StackItem.Null : engine.ResultStack.Peek(); return engine.State != VMState.FAULT; @@ -621,7 +632,7 @@ private bool OnInvokeWithResult(UInt160 scriptHash, string operation, out StackI private void PrintExecutionOutput(ApplicationEngine engine, bool showStack = true) { ConsoleHelper.Info("VM State: ", engine.State.ToString()); - ConsoleHelper.Info("Gas Consumed: ", new BigDecimal((BigInteger)engine.GasConsumed, NativeContract.GAS.Decimals).ToString()); + ConsoleHelper.Info("Gas Consumed: ", new BigDecimal((BigInteger)engine.FeeConsumed, NativeContract.GAS.Decimals).ToString()); if (showStack) ConsoleHelper.Info("Result Stack: ", new JArray(engine.ResultStack.Select(p => p.ToJson())).ToString()); diff --git a/src/Neo.CLI/Neo.CLI.csproj b/src/Neo.CLI/Neo.CLI.csproj index bb52675ec4..a9d4c9919e 100644 --- a/src/Neo.CLI/Neo.CLI.csproj +++ b/src/Neo.CLI/Neo.CLI.csproj @@ -10,6 +10,7 @@ Neo.CLI neo.ico enable + $(SolutionDir)/bin/$(AssemblyTitle) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index e79a31c312..6adb47eb03 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -6,8 +6,8 @@ "Active": false }, "Storage": { - "Engine": "LevelDBStore", // Candidates [MemoryStore, LevelDBStore, RocksDBStore] - "Path": "Data_LevelDB_{0}" // {0} is a placeholder for the network id + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" }, "P2P": { "Port": 40333, diff --git a/src/Neo.CLI/config.fs.testnet.json b/src/Neo.CLI/config.fs.testnet.json index b167f35b81..ca0f0225e6 100644 --- a/src/Neo.CLI/config.fs.testnet.json +++ b/src/Neo.CLI/config.fs.testnet.json @@ -6,8 +6,8 @@ "Active": false }, "Storage": { - "Engine": "LevelDBStore", // Candidates [MemoryStore, LevelDBStore, RocksDBStore] - "Path": "Data_LevelDB_{0}" // {0} is a placeholder for the network id + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" }, "P2P": { "Port": 50333, diff --git a/src/Neo.CLI/config.json.md b/src/Neo.CLI/config.json.md new file mode 100644 index 0000000000..da3bbaec6e --- /dev/null +++ b/src/Neo.CLI/config.json.md @@ -0,0 +1,85 @@ +# README for Application and Protocol Configuration JSON File + +This README provides an explanation for each field in the JSON configuration file for a NEO node. + +## ApplicationConfiguration + +### Logger +- **Path**: Directory where log files are stored. Default is "Logs". +- **ConsoleOutput**: Boolean flag to enable or disable console output for logging. Default is `false`. +- **Active**: Boolean flag to activate or deactivate the logger. Default is `false`. + +### Storage +- **Engine**: Specifies the storage engine used by the node. Possible values are: + - `MemoryStore` + - `LevelDBStore` + - `RocksDBStore` +- **Path**: Path to the data storage directory. `{0}` is a placeholder for the network ID. + +### P2P +- **Port**: Port number for the P2P network. MainNet is `10333`, TestNet is `20333`. +- **MinDesiredConnections**: Minimum number of desired P2P connections. Default is `10`. +- **MaxConnections**: Maximum number of P2P connections. Default is `40`. +- **MaxConnectionsPerAddress**: Maximum number of connections allowed per address. Default is `3`. + +### UnlockWallet +- **Path**: Path to the wallet file. +- **Password**: Password for the wallet. +- **IsActive**: Boolean flag to activate or deactivate the wallet. Default is `false`. + +### Contracts +- **NeoNameService**: Script hash of the Neo Name Service contract. MainNet is `0x50ac1c37690cc2cfc594472833cf57505d5f46de`, TestNet is `0x50ac1c37690cc2cfc594472833cf57505d5f46de`. + +### Plugins +- **DownloadUrl**: URL to download plugins, typically from the NEO project's GitHub releases. Default is `https://api.github.com/repos/neo-project/neo/releases`. + +## ProtocolConfiguration + +### Network +- **Network**: Network ID for the NEO network. MainNet is `860833102`, TestNet is `894710606` + +### AddressVersion +- **AddressVersion**: Version byte used in NEO address generation. Default is `53`. + +### MillisecondsPerBlock +- **MillisecondsPerBlock**: Time interval between blocks in milliseconds. Default is `15000` (15 seconds). + +### MaxTransactionsPerBlock +- **MaxTransactionsPerBlock**: Maximum number of transactions allowed per block. Default is `512`. + +### MemoryPoolMaxTransactions +- **MemoryPoolMaxTransactions**: Maximum number of transactions that can be held in the memory pool. Default is `50000`. + +### MaxTraceableBlocks +- **MaxTraceableBlocks**: Maximum number of blocks that can be traced back. Default is `2102400`. + +### Hardforks +- **HF_Aspidochelone**: Block height for the Aspidochelone hard fork. MainNet is `1730000`, TestNet is `210000`. +- **HF_Basilisk**: Block height for the Basilisk hard fork. MainNet is `4120000`, TestNet is `2680000`. +- **HF_Cockatrice**: Block height for the Cockatrice hard fork. MainNet is `5450000`, TestNet is `3967000`. + +### InitialGasDistribution +- **InitialGasDistribution**: Total amount of GAS distributed initially. Default is `5,200,000,000,000,000 Datoshi` (`52,000,000 GAS`). + +### ValidatorsCount +- **ValidatorsCount**: Number of consensus validators. Default is `7`. + +### StandbyCommittee +- **StandbyCommittee**: List of public keys for the standby committee members. + +### SeedList +- **SeedList**: List of seed nodes with their addresses and ports. + - MainNet addresses are: + - `seed1.neo.org:10333` + - `seed2.neo.org:10333` + - `seed3.neo.org:10333` + - `seed4.neo.org:10333` + - `seed5.neo.org:10333` + - TestNet addresses are: + - `seed1t5.neo.org:20333` + - `seed2t5.neo.org:20333` + - `seed3t5.neo.org:20333` + - `seed4t5.neo.org:20333` + - `seed5t5.neo.org:20333` + +This configuration file is essential for setting up and running a NEO node, ensuring proper logging, storage, network connectivity, and consensus protocol parameters. diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index c9544a337f..a32cad5ad5 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -6,8 +6,8 @@ "Active": false }, "Storage": { - "Engine": "LevelDBStore", // Candidates [MemoryStore, LevelDBStore, RocksDBStore] - "Path": "Data_LevelDB_{0}" // {0} is a placeholder for the network id + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" }, "P2P": { "Port": 10333, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index 6e566c7ce1..4350fc62f2 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -6,8 +6,8 @@ "Active": false }, "Storage": { - "Engine": "LevelDBStore", // Candidates [MemoryStore, LevelDBStore, RocksDBStore] - "Path": "Data_LevelDB_{0}" // {0} is a placeholder for the network id + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" }, "P2P": { "Port": 20333, diff --git a/src/Neo.ConsoleService/Neo.ConsoleService.csproj b/src/Neo.ConsoleService/Neo.ConsoleService.csproj index 206e18235e..9b3ad32dfe 100644 --- a/src/Neo.ConsoleService/Neo.ConsoleService.csproj +++ b/src/Neo.ConsoleService/Neo.ConsoleService.csproj @@ -4,6 +4,7 @@ netstandard2.1;net8.0 Neo.ConsoleService enable + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Neo.Cryptography.BLS12_381/Neo.Cryptography.BLS12_381.csproj b/src/Neo.Cryptography.BLS12_381/Neo.Cryptography.BLS12_381.csproj index 800699719f..d5313d9eab 100644 --- a/src/Neo.Cryptography.BLS12_381/Neo.Cryptography.BLS12_381.csproj +++ b/src/Neo.Cryptography.BLS12_381/Neo.Cryptography.BLS12_381.csproj @@ -5,6 +5,8 @@ netstandard2.1;net8.0 enable enable + Neo.Cryptography.BLS12_381 + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Neo.Extensions/Neo.Extensions.csproj b/src/Neo.Extensions/Neo.Extensions.csproj index 71330a05a3..c6d549be6a 100644 --- a/src/Neo.Extensions/Neo.Extensions.csproj +++ b/src/Neo.Extensions/Neo.Extensions.csproj @@ -3,7 +3,9 @@ netstandard2.1;net8.0 enable + Neo.Extensions NEO;Blockchain;Extensions + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Neo.GUI/GUI/InvokeContractDialog.cs b/src/Neo.GUI/GUI/InvokeContractDialog.cs index 4e46799f5c..d8a8a6b66f 100644 --- a/src/Neo.GUI/GUI/InvokeContractDialog.cs +++ b/src/Neo.GUI/GUI/InvokeContractDialog.cs @@ -90,12 +90,12 @@ private void button5_Click(object sender, EventArgs e) using ApplicationEngine engine = ApplicationEngine.Run(tx_test.Script, Service.NeoSystem.StoreView, container: tx_test); StringBuilder sb = new StringBuilder(); sb.AppendLine($"VM State: {engine.State}"); - sb.AppendLine($"Gas Consumed: {engine.GasConsumed}"); + sb.AppendLine($"Gas Consumed: {engine.FeeConsumed}"); sb.AppendLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToParameter().ToJson()))}"); textBox7.Text = sb.ToString(); if (engine.State != VMState.FAULT) { - label7.Text = engine.GasConsumed + " gas"; + label7.Text = engine.FeeConsumed + " gas"; button3.Enabled = true; } else diff --git a/src/Neo.GUI/Neo.GUI.csproj b/src/Neo.GUI/Neo.GUI.csproj index 34e515b159..014459be4c 100644 --- a/src/Neo.GUI/Neo.GUI.csproj +++ b/src/Neo.GUI/Neo.GUI.csproj @@ -10,6 +10,8 @@ true Neo.GUI neo.ico + false + $(SolutionDir)/bin/$(AssemblyTitle) @@ -61,4 +63,4 @@ - \ No newline at end of file + diff --git a/src/Neo.IO/Neo.IO.csproj b/src/Neo.IO/Neo.IO.csproj index f920a40fd5..a1a0a9ea2e 100644 --- a/src/Neo.IO/Neo.IO.csproj +++ b/src/Neo.IO/Neo.IO.csproj @@ -4,7 +4,9 @@ netstandard2.1;net8.0 true enable + Neo.IO NEO;Blockchain;IO + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Neo.Json/Neo.Json.csproj b/src/Neo.Json/Neo.Json.csproj index cc3ea45278..3d75276dec 100644 --- a/src/Neo.Json/Neo.Json.csproj +++ b/src/Neo.Json/Neo.Json.csproj @@ -4,7 +4,9 @@ netstandard2.1;net8.0 enable enable + Neo.Json NEO;JSON + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Neo.VM/Neo.VM.csproj b/src/Neo.VM/Neo.VM.csproj index a9157f5bcf..9315a850df 100644 --- a/src/Neo.VM/Neo.VM.csproj +++ b/src/Neo.VM/Neo.VM.csproj @@ -4,6 +4,8 @@ netstandard2.1;net8.0 true enable + Neo.VM + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Neo/Hardfork.cs b/src/Neo/Hardfork.cs index 9ef6a63c1c..7bd3cc0aef 100644 --- a/src/Neo/Hardfork.cs +++ b/src/Neo/Hardfork.cs @@ -15,6 +15,7 @@ public enum Hardfork : byte { HF_Aspidochelone, HF_Basilisk, - HF_Cockatrice + HF_Cockatrice, + HF_Domovoi } } diff --git a/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs b/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs index 211ac14117..e1fa5fae62 100644 --- a/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs +++ b/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs @@ -62,7 +62,7 @@ internal ApplicationExecuted(ApplicationEngine engine) Transaction = engine.ScriptContainer as Transaction; Trigger = engine.Trigger; VMState = engine.State; - GasConsumed = engine.GasConsumed; + GasConsumed = engine.FeeConsumed; Exception = engine.FaultException; Stack = engine.ResultStack.ToArray(); Notifications = engine.Notifications.ToArray(); diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 6a1ba44504..707b94fa4c 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -3,7 +3,9 @@ netstandard2.1;net8.0 true + Neo NEO;AntShares;Blockchain;Smart Contract + $(SolutionDir)/bin/$(PackageId) @@ -27,6 +29,7 @@ + diff --git a/src/Neo/Network/P2P/Payloads/Transaction.cs b/src/Neo/Network/P2P/Payloads/Transaction.cs index 16417beb43..b922674d91 100644 --- a/src/Neo/Network/P2P/Payloads/Transaction.cs +++ b/src/Neo/Network/P2P/Payloads/Transaction.cs @@ -46,7 +46,9 @@ public class Transaction : IEquatable, IInventory, IInteroperable private byte version; private uint nonce; + // In the unit of datoshi, 1 datoshi = 1e-8 GAS private long sysfee; + // In the unit of datoshi, 1 datoshi = 1e-8 GAS private long netfee; private uint validUntilBlock; private Signer[] _signers; @@ -372,26 +374,26 @@ public virtual VerifyResult VerifyStateDependent(ProtocolSettings settings, Data return VerifyResult.InvalidAttribute; else attributesFee += attribute.CalculateNetworkFee(snapshot, this); - long net_fee = NetworkFee - (Size * NativeContract.Policy.GetFeePerByte(snapshot)) - attributesFee; - if (net_fee < 0) return VerifyResult.InsufficientFunds; + long netFeeDatoshi = NetworkFee - (Size * NativeContract.Policy.GetFeePerByte(snapshot)) - attributesFee; + if (netFeeDatoshi < 0) return VerifyResult.InsufficientFunds; - if (net_fee > MaxVerificationGas) net_fee = MaxVerificationGas; + if (netFeeDatoshi > MaxVerificationGas) netFeeDatoshi = MaxVerificationGas; uint execFeeFactor = NativeContract.Policy.GetExecFeeFactor(snapshot); for (int i = 0; i < hashes.Length; i++) { if (IsSignatureContract(witnesses[i].VerificationScript.Span)) - net_fee -= execFeeFactor * SignatureContractCost(); + netFeeDatoshi -= execFeeFactor * SignatureContractCost(); else if (IsMultiSigContract(witnesses[i].VerificationScript.Span, out int m, out int n)) { - net_fee -= execFeeFactor * MultiSignatureContractCost(m, n); + netFeeDatoshi -= execFeeFactor * MultiSignatureContractCost(m, n); } else { - if (!this.VerifyWitness(settings, snapshot, hashes[i], witnesses[i], net_fee, out long fee)) + if (!this.VerifyWitness(settings, snapshot, hashes[i], witnesses[i], netFeeDatoshi, out long fee)) return VerifyResult.Invalid; - net_fee -= fee; + netFeeDatoshi -= fee; } - if (net_fee < 0) return VerifyResult.InsufficientFunds; + if (netFeeDatoshi < 0) return VerifyResult.InsufficientFunds; } return VerifyResult.Succeed; } diff --git a/src/Neo/Persistence/SnapshotCache.cs b/src/Neo/Persistence/SnapshotCache.cs index 24036b41dc..6731e5342f 100644 --- a/src/Neo/Persistence/SnapshotCache.cs +++ b/src/Neo/Persistence/SnapshotCache.cs @@ -48,7 +48,7 @@ protected override void DeleteInternal(StorageKey key) public override void Commit() { base.Commit(); - snapshot.Commit(); + snapshot?.Commit(); } protected override bool ContainsInternal(StorageKey key) diff --git a/src/Neo/ProtocolSettings.cs b/src/Neo/ProtocolSettings.cs index f03e5ffaf9..19011dc24c 100644 --- a/src/Neo/ProtocolSettings.cs +++ b/src/Neo/ProtocolSettings.cs @@ -93,6 +93,7 @@ public record ProtocolSettings /// /// Indicates the amount of gas to distribute during initialization. + /// In the unit of datoshi, 1 GAS = 1e8 datoshi /// public ulong InitialGasDistribution { get; init; } diff --git a/src/Neo/SmartContract/ApplicationEngine.Contract.cs b/src/Neo/SmartContract/ApplicationEngine.Contract.cs index 6f4b257016..e5c1c762a7 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Contract.cs @@ -120,10 +120,11 @@ protected internal CallFlags GetCallFlags() /// The hash of the account. internal protected UInt160 CreateStandardAccount(ECPoint pubKey) { + // In the unit of datoshi, 1 datoshi = 1e-8 GAS long fee = IsHardforkEnabled(Hardfork.HF_Aspidochelone) ? CheckSigPrice : 1 << 8; - AddGas(fee * ExecFeeFactor); + AddFee(fee * ExecFeeFactor); return Contract.CreateSignatureRedeemScript(pubKey).ToScriptHash(); } @@ -136,10 +137,11 @@ internal protected UInt160 CreateStandardAccount(ECPoint pubKey) /// The hash of the account. internal protected UInt160 CreateMultisigAccount(int m, ECPoint[] pubKeys) { + // In the unit of datoshi, 1 datoshi = 1e-8 GAS long fee = IsHardforkEnabled(Hardfork.HF_Aspidochelone) ? CheckSigPrice * pubKeys.Length : 1 << 8; - AddGas(fee * ExecFeeFactor); + AddFee(fee * ExecFeeFactor); return Contract.CreateMultiSigRedeemScript(m, pubKeys).ToScriptHash(); } diff --git a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs index 1a8b2c7d6d..b63f1287f0 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs @@ -20,6 +20,7 @@ partial class ApplicationEngine { /// /// The price of System.Crypto.CheckSig. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS /// public const long CheckSigPrice = 1 << 15; @@ -66,7 +67,7 @@ protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); - AddGas(CheckSigPrice * n * ExecFeeFactor); + AddFee(CheckSigPrice * n * ExecFeeFactor); try { for (int i = 0, j = 0; i < m && j < n;) diff --git a/src/Neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/src/Neo/SmartContract/ApplicationEngine.OpCodePrices.cs index 16a0a95944..17e4bd6bfb 100644 --- a/src/Neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/src/Neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -221,6 +221,10 @@ partial class ApplicationEngine [OpCode.CONVERT] = 1 << 13, }; + /// + /// The prices of all the opcodes. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS + /// public static readonly long[] OpCodePriceTable = new long[byte.MaxValue]; /// diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 293b245bd7..e54529f6d1 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -305,6 +305,7 @@ protected internal int GetInvocationCounter() protected internal BigInteger GetRandom() { byte[] buffer; + // In the unit of datoshi, 1 datoshi = 1e-8 GAS long price; if (IsHardforkEnabled(Hardfork.HF_Aspidochelone)) { @@ -316,7 +317,7 @@ protected internal BigInteger GetRandom() buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network); price = 1 << 4; } - AddGas(price * ExecFeeFactor); + AddFee(price * ExecFeeFactor); return new BigInteger(buffer, isUnsigned: true); } @@ -406,26 +407,31 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s /// /// The hash of the specified contract. It can be set to to get all notifications. /// The notifications sent during the execution. - protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) + protected internal Array GetNotifications(UInt160 hash) { IEnumerable notifications = Notifications; if (hash != null) // must filter by scriptHash notifications = notifications.Where(p => p.ScriptHash == hash); - NotifyEventArgs[] array = notifications.ToArray(); + var array = notifications.ToArray(); if (array.Length > Limits.MaxStackSize) throw new InvalidOperationException(); - return array; + Array notifyArray = new(ReferenceCounter); + foreach (var notify in array) + { + notifyArray.Add(notify.ToStackItem(ReferenceCounter, this)); + } + return notifyArray; } /// /// The implementation of System.Runtime.BurnGas. /// Burning GAS to benefit the NEO ecosystem. /// - /// The amount of GAS to burn. - protected internal void BurnGas(long gas) + /// The amount of GAS to burn, in the unit of datoshi, 1 datoshi = 1e-8 GAS + protected internal void BurnGas(long datoshi) { - if (gas <= 0) + if (datoshi <= 0) throw new InvalidOperationException("GAS must be positive."); - AddGas(gas); + AddFee(datoshi); } /// diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index 3a8bb9d122..fbd452d6cc 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -194,7 +194,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) else newDataSize = (item.Value.Length - 1) / 4 + 1 + value.Length - item.Value.Length; } - AddGas(newDataSize * StoragePrice); + AddFee(newDataSize * StoragePrice); item.Value = value; } diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 14dedf8e7c..fab17a2bb1 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -36,6 +36,7 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The maximum cost that can be spent when a contract is executed in test mode. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS /// public const long TestModeGas = 20_00000000; @@ -50,7 +51,9 @@ public partial class ApplicationEngine : ExecutionEngine public static event EventHandler Log; private static Dictionary services; - private readonly long gas_amount; + // Total amount of GAS spent to execute. + // In the unit of datoshi, 1 datoshi = 1e-8 GAS, 1 GAS = 1e8 datoshi + private readonly long _feeAmount; private Dictionary states; private readonly DataCache originalSnapshot; private List notifications; @@ -58,6 +61,7 @@ public partial class ApplicationEngine : ExecutionEngine private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); internal readonly uint ExecFeeFactor; + // In the unit of datoshi, 1 datoshi = 1e-8 GAS internal readonly uint StoragePrice; private byte[] nonceData; @@ -105,13 +109,22 @@ public partial class ApplicationEngine : ExecutionEngine /// /// GAS spent to execute. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS, 1 GAS = 1e8 datoshi /// + [Obsolete("This property is deprecated. Use FeeConsumed instead.")] public long GasConsumed { get; private set; } = 0; + /// + /// GAS spent to execute. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS, 1 GAS = 1e8 datoshi + /// + public long FeeConsumed { get; private set; } = 0; + /// /// The remaining GAS that can be spent in order to complete the execution. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS, 1 GAS = 1e8 datoshi /// - public long GasLeft => gas_amount - GasConsumed; + public long GasLeft => _feeAmount - FeeConsumed; /// /// The exception that caused the execution to terminate abnormally. This field could be if no exception is thrown. @@ -154,7 +167,7 @@ public virtual UInt160 CallingScriptHash /// The snapshot used by the engine during execution. /// The block being persisted. It should be if the is . /// The used by the engine. - /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. + /// The maximum gas, in the unit of datoshi, used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The jump table to be used by the . protected unsafe ApplicationEngine( @@ -167,7 +180,7 @@ protected unsafe ApplicationEngine( originalSnapshot = snapshot; PersistingBlock = persistingBlock; ProtocolSettings = settings; - gas_amount = gas; + _feeAmount = gas; Diagnostic = diagnostic; ExecFeeFactor = snapshot is null || persistingBlock?.Index == 0 ? PolicyContract.DefaultExecFeeFactor : NativeContract.Policy.GetExecFeeFactor(snapshot); StoragePrice = snapshot is null || persistingBlock?.Index == 0 ? PolicyContract.DefaultStoragePrice : NativeContract.Policy.GetStoragePrice(snapshot); @@ -235,13 +248,15 @@ protected static void OnSysCall(ExecutionEngine engine, Instruction instruction) #endregion /// - /// Adds GAS to and checks if it has exceeded the maximum limit. + /// Adds GAS to and checks if it has exceeded the maximum limit. /// - /// The amount of GAS to be added. - protected internal void AddGas(long gas) + /// The amount of GAS, in the unit of datoshi, 1 datoshi = 1e-8 GAS, to be added. + protected internal void AddFee(long datoshi) { - GasConsumed = checked(GasConsumed + gas); - if (GasConsumed > gas_amount) +#pragma warning disable CS0618 // Type or member is obsolete + FeeConsumed = GasConsumed = checked(FeeConsumed + datoshi); +#pragma warning restore CS0618 // Type or member is obsolete + if (FeeConsumed > _feeAmount) throw new InvalidOperationException("Insufficient GAS."); } @@ -271,14 +286,18 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe if (NativeContract.Policy.IsBlocked(Snapshot, contract.Hash)) throw new InvalidOperationException($"The contract {contract.Hash} has been blocked."); + ExecutionContext currentContext = CurrentContext; + ExecutionContextState state = currentContext.GetState(); if (method.Safe) { flags &= ~(CallFlags.WriteStates | CallFlags.AllowNotify); } else { - ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); - if (currentContract?.CanCall(contract, method.Name) == false) + var executingContract = IsHardforkEnabled(Hardfork.HF_Domovoi) + ? state.Contract // use executing contract state to avoid possible contract update/destroy side-effects, ref. https://github.com/neo-project/neo/pull/3290. + : NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + if (executingContract?.CanCall(contract, method.Name) == false) throw new InvalidOperationException($"Cannot Call Method {method.Name} Of Contract {contract.Hash} From Contract {CurrentScriptHash}"); } @@ -291,8 +310,6 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe invocationCounter[contract.Hash] = 1; } - ExecutionContext currentContext = CurrentContext; - ExecutionContextState state = currentContext.GetState(); CallFlags callingFlags = state.CallFlags; if (args.Count != method.Parameters.Length) throw new InvalidOperationException($"Method {method} Expects {method.Parameters.Length} Arguments But Receives {args.Count} Arguments"); @@ -372,7 +389,7 @@ internal override void UnloadContext(ExecutionContext context) /// The snapshot used by the engine during execution. /// The block being persisted. It should be if the is . /// The used by the engine. - /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. + /// The maximum gas used in this execution, in the unit of datoshi. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) @@ -421,7 +438,7 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr }); // Call initialization - var init = contract.Manifest.Abi.GetMethod("_initialize", 0); + var init = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Initialize, ContractBasicMethod.InitializePCount); if (init != null) { LoadContext(context.Clone(init.Offset)); @@ -555,7 +572,7 @@ internal protected void ValidateCallFlags(CallFlags requiredCallFlags) protected virtual void OnSysCall(InteropDescriptor descriptor) { ValidateCallFlags(descriptor.RequiredCallFlags); - AddGas(descriptor.FixedPrice * ExecFeeFactor); + AddFee(descriptor.FixedPrice * ExecFeeFactor); object[] parameters = new object[descriptor.Parameters.Count]; for (int i = 0; i < parameters.Length; i++) @@ -569,7 +586,7 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) protected override void PreExecuteInstruction(Instruction instruction) { Diagnostic?.PreExecuteInstruction(instruction); - AddGas(ExecFeeFactor * OpCodePriceTable[(byte)instruction.OpCode]); + AddFee(ExecFeeFactor * OpCodePriceTable[(byte)instruction.OpCode]); } protected override void PostExecuteInstruction(Instruction instruction) @@ -627,7 +644,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The block being persisted. /// The used by the engine. /// The initial position of the instruction pointer. - /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. + /// The maximum gas, in the unit of datoshi, used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) diff --git a/src/Neo/SmartContract/ContractBasicMethod.cs b/src/Neo/SmartContract/ContractBasicMethod.cs new file mode 100644 index 0000000000..7897f50c0a --- /dev/null +++ b/src/Neo/SmartContract/ContractBasicMethod.cs @@ -0,0 +1,122 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// ContractBasicMethod.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.SmartContract +{ + /// + /// This class provides a guideline for basic methods used in the Neo blockchain, offering + /// a generalized interaction mechanism for smart contract deployment, verification, updates, and destruction. + /// + public record ContractBasicMethod + { + /// + /// The verification method. This must be called when withdrawing tokens from the contract. + /// If the contract address is included in the transaction signature, this method verifies the signature. + /// Example: + /// + /// public static bool Verify() => Runtime.CheckWitness(Owner); + /// + /// + /// { + /// "name": "verify", + /// "safe": false, + /// "parameters": [], + /// "returntype": "bool" + /// } + /// + /// + public static string Verify { get; } = "verify"; + + /// + /// The initialization method. Compiled into the file if any function uses the initialize statement. + /// These functions are executed first when loading the contract. + /// Example: + /// + /// private static readonly UInt160 owner = "NdUL5oDPD159KeFpD5A9zw5xNF1xLX6nLT"; + /// + /// + public static string Initialize { get; } = "_initialize"; + + /// + /// The deployment method. Automatically executed by the ContractManagement contract when a contract is first deployed or updated. + /// + /// { + /// "name": "_deploy", + /// "safe": false, + /// "parameters": [ + /// { + /// "name": "data", + /// "type": "Any" + /// }, + /// { + /// "name": "update", + /// "type": "Boolean" + /// } + /// ], + /// "returntype": "Void" + /// } + /// + /// + public static string Deploy { get; } = "_deploy"; + + /// + /// The update method. Requires or , or both, and is passed to _deploy. + /// Should verify the signer's address using SYSCALL Neo.Runtime.CheckWitness. + /// + /// { + /// "name": "update", + /// "safe": false, + /// "parameters": [ + /// { + /// "name": "nefFile", + /// "type": "ByteArray" + /// }, + /// { + /// "name": "manifest", + /// "type": "ByteArray" + /// }, + /// { + /// "name": "data", + /// "type": "Any" + /// } + /// ], + /// "returntype": "Void" + /// } + /// + /// + public static string Update { get; } = "update"; + + /// + /// The destruction method. Deletes all the storage of the contract. + /// Should verify the signer's address using SYSCALL Neo.Runtime.CheckWitness. + /// Any tokens in the contract must be transferred before destruction. + /// + /// { + /// "name": "destroy", + /// "safe": false, + /// "parameters": [], + /// "returntype": "Void" + /// } + /// + /// + public static string Destroy { get; } = "destroy"; + + /// + /// Parameter counts for the methods. + /// -1 represents the method can take arbitrary parameters. + /// + public static int VerifyPCount { get; } = -1; + public static int InitializePCount { get; } = 0; + public static int DeployPCount { get; } = 2; + public static int UpdatePCount { get; } = 3; + public static int DestroyPCount { get; } = 0; + } +} diff --git a/src/Neo/SmartContract/DeployedContract.cs b/src/Neo/SmartContract/DeployedContract.cs index 0587a029e5..a3f9cfd9fb 100644 --- a/src/Neo/SmartContract/DeployedContract.cs +++ b/src/Neo/SmartContract/DeployedContract.cs @@ -32,7 +32,7 @@ public DeployedContract(ContractState contract) Script = null; ScriptHash = contract.Hash; - ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index c0c694fc4e..ae31d66a50 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -31,11 +31,13 @@ public static class Helper { /// /// The maximum GAS that can be consumed when is called. + /// The unit is datoshi, 1 datoshi = 1e-8 GAS /// public const long MaxVerificationGas = 1_50000000; /// /// Calculates the verification fee for a signature address. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS /// /// The calculated cost. public static long SignatureContractCost() => @@ -45,6 +47,7 @@ public static long SignatureContractCost() => /// /// Calculates the verification fee for a multi-signature address. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS /// /// The minimum number of correct signatures that need to be provided in order for the verification to pass. /// The number of public keys in the account. @@ -285,12 +288,12 @@ public static UInt160 ToScriptHash(this ReadOnlySpan script) /// The to be verified. /// The to be used for the verification. /// The snapshot used to read data. - /// The maximum GAS that can be used. + /// The maximum GAS that can be used, in the unit of datoshi, 1 datoshi = 1e-8 GAS. /// if the is verified as valid; otherwise, . - public static bool VerifyWitnesses(this IVerifiable verifiable, ProtocolSettings settings, DataCache snapshot, long gas) + public static bool VerifyWitnesses(this IVerifiable verifiable, ProtocolSettings settings, DataCache snapshot, long datoshi) { - if (gas < 0) return false; - if (gas > MaxVerificationGas) gas = MaxVerificationGas; + if (datoshi < 0) return false; + if (datoshi > MaxVerificationGas) datoshi = MaxVerificationGas; UInt160[] hashes; try @@ -304,14 +307,14 @@ public static bool VerifyWitnesses(this IVerifiable verifiable, ProtocolSettings if (hashes.Length != verifiable.Witnesses.Length) return false; for (int i = 0; i < hashes.Length; i++) { - if (!verifiable.VerifyWitness(settings, snapshot, hashes[i], verifiable.Witnesses[i], gas, out long fee)) + if (!verifiable.VerifyWitness(settings, snapshot, hashes[i], verifiable.Witnesses[i], datoshi, out long fee)) return false; - gas -= fee; + datoshi -= fee; } return true; } - internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings settings, DataCache snapshot, UInt160 hash, Witness witness, long gas, out long fee) + internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings settings, DataCache snapshot, UInt160 hash, Witness witness, long datoshi, out long fee) { fee = 0; Script invocationScript; @@ -323,13 +326,13 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings { return false; } - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, gas)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, datoshi)) { if (witness.VerificationScript.Length == 0) { ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount); if (md?.ReturnType != ContractParameterType.Boolean) return false; engine.LoadContract(cs, md, CallFlags.ReadOnly); } @@ -357,7 +360,7 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings if (engine.Execute() == VMState.FAULT) return false; if (!engine.ResultStack.Peek().GetBoolean()) return false; - fee = engine.GasConsumed; + fee = engine.FeeConsumed; } return true; } diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index e7a7e122f2..c533f029a6 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -60,7 +60,7 @@ internal override ContractTask InitializeAsync(ApplicationEngine engine, Hardfor private async ContractTask OnDeployAsync(ApplicationEngine engine, ContractState contract, StackItem data, bool update) { - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Deploy, ContractBasicMethod.DeployPCount); if (md is not null) await engine.CallFromNativeContractAsync(Hash, contract.Hash, md.Name, data, update); engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() }); @@ -118,11 +118,12 @@ internal override async ContractTask OnPersistAsync(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private long GetMinimumDeploymentFee(DataCache snapshot) { + // In the unit of datoshi, 1 datoshi = 1e-8 GAS return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_MinimumDeploymentFee)]; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] - private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) + private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value/* In the unit of datoshi, 1 datoshi = 1e-8 GAS*/) { if (value < 0) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); @@ -218,7 +219,7 @@ private async ContractTask Deploy(ApplicationEngine engine, byte[ if (manifest.Length == 0) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); - engine.AddGas(Math.Max( + engine.AddFee(Math.Max( engine.StoragePrice * (nefFile.Length + manifest.Length), GetMinimumDeploymentFee(engine.Snapshot) )); @@ -264,7 +265,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man { if (nefFile is null && manifest is null) throw new ArgumentException(); - engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); + engine.AddFee(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(false); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); diff --git a/src/Neo/SmartContract/Native/CryptoLib.cs b/src/Neo/SmartContract/Native/CryptoLib.cs index 452dd31faa..9027298752 100644 --- a/src/Neo/SmartContract/Native/CryptoLib.cs +++ b/src/Neo/SmartContract/Native/CryptoLib.cs @@ -21,12 +21,6 @@ namespace Neo.SmartContract.Native /// public sealed partial class CryptoLib : NativeContract { - private static readonly Dictionary curves = new() - { - [NamedCurve.secp256k1] = ECCurve.Secp256k1, - [NamedCurve.secp256r1] = ECCurve.Secp256r1, - }; - private static readonly Dictionary s_curves = new() { [NamedCurveHash.secp256k1SHA256] = (ECCurve.Secp256k1, Hasher.SHA256), @@ -106,12 +100,15 @@ public static bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signatu } // This is for solving the hardfork issue in https://github.com/neo-project/neo/pull/3209 - [ContractMethod(true, Hardfork.HF_Cockatrice, CpuFee = 1 << 15)] - public static bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signature, NamedCurve curve) + [ContractMethod(true, Hardfork.HF_Cockatrice, CpuFee = 1 << 15, Name = "verifyWithECDsa")] + public static bool VerifyWithECDsaV0(byte[] message, byte[] pubkey, byte[] signature, NamedCurveHash curve) { + if (curve != NamedCurveHash.secp256k1SHA256 && curve != NamedCurveHash.secp256r1SHA256) + throw new ArgumentOutOfRangeException(nameof(curve)); + try { - return Crypto.VerifySignature(message, signature, pubkey, curves[curve]); + return Crypto.VerifySignature(message, signature, pubkey, s_curves[curve].Curve); } catch (ArgumentException) { diff --git a/src/Neo/SmartContract/Native/NamedCurve.cs b/src/Neo/SmartContract/Native/NamedCurve.cs deleted file mode 100644 index 8c7a9107e9..0000000000 --- a/src/Neo/SmartContract/Native/NamedCurve.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2015-2024 The Neo Project. -// -// NamedCurve.cs file belongs to the neo project and is free -// software distributed under the MIT software license, see the -// accompanying file LICENSE in the main directory of the -// repository or http://www.opensource.org/licenses/mit-license.php -// for more details. -// -// Redistribution and use in source and binary forms with or without -// modifications are permitted. - -using System; - -namespace Neo.SmartContract.Native -{ - /// - /// Represents the named curve used in ECDSA. This enum is obsolete - /// and will be removed in future versions. Please, use an extended instead. - /// - /// - /// https://tools.ietf.org/html/rfc4492#section-5.1.1 - /// - [Obsolete("NamedCurve enum is obsolete and will be removed in future versions. Please, use an extended NamedCurveHash instead.")] - public enum NamedCurve : byte - { - /// - /// The secp256k1 curve. - /// - [Obsolete("secp256k1 value is obsolete and will be removed in future versions. Please, use NamedCurveHash.secp256k1SHA256 for compatible behaviour.")] - secp256k1 = 22, - - /// - /// The secp256r1 curve, which known as prime256v1 or nistP-256. - /// - [Obsolete("secp256r1 value is obsolete and will be removed in future versions. Please, use NamedCurveHash.secp256r1SHA256 for compatible behaviour.")] - secp256r1 = 23 - } -} diff --git a/src/Neo/SmartContract/Native/NamedCurveHash.cs b/src/Neo/SmartContract/Native/NamedCurveHash.cs index 8bd63bf874..653ed3aa88 100644 --- a/src/Neo/SmartContract/Native/NamedCurveHash.cs +++ b/src/Neo/SmartContract/Native/NamedCurveHash.cs @@ -13,7 +13,6 @@ namespace Neo.SmartContract.Native { /// /// Represents a pair of the named curve used in ECDSA and a hash algorithm used to hash message. - /// This is a compatible extension of an obsolete enum. /// public enum NamedCurveHash : byte { diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 03815b3fae..1cc244408d 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -35,7 +35,7 @@ public class CacheEntry public byte[] Script { get; set; } } - internal Dictionary NativeContracts { get; set; } = new Dictionary(); + internal Dictionary NativeContracts { get; set; } = new(); public CacheEntry GetAllowedMethods(NativeContract native, ApplicationEngine engine) { @@ -48,12 +48,12 @@ public CacheEntry GetAllowedMethods(NativeContract native, ApplicationEngine eng } } - public delegate bool IsHardforkEnabledDelegate(Hardfork hf, uint index); - private static readonly List contractsList = new(); - private static readonly Dictionary contractsDictionary = new(); - private readonly ImmutableHashSet usedHardforks; - private readonly ReadOnlyCollection methodDescriptors; - private readonly ReadOnlyCollection eventsDescriptors; + public delegate bool IsHardforkEnabledDelegate(Hardfork hf, uint blockHeight); + private static readonly List s_contractsList = []; + private static readonly Dictionary s_contractsDictionary = new(); + private readonly ImmutableHashSet _usedHardforks; + private readonly ReadOnlyCollection _methodDescriptors; + private readonly ReadOnlyCollection _eventsDescriptors; private static int id_counter = 0; #region Named Native Contracts @@ -108,7 +108,7 @@ public CacheEntry GetAllowedMethods(NativeContract native, ApplicationEngine eng /// /// Gets all native contracts. /// - public static IReadOnlyCollection Contracts { get; } = contractsList; + public static IReadOnlyCollection Contracts { get; } = s_contractsList; /// /// The name of the native contract. @@ -139,17 +139,17 @@ protected NativeContract() // Reflection to get the methods - List listMethods = new(); + List listMethods = []; foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { ContractMethodAttribute attribute = member.GetCustomAttribute(); if (attribute is null) continue; listMethods.Add(new ContractMethodMetadata(member, attribute)); } - methodDescriptors = listMethods.OrderBy(p => p.Name, StringComparer.Ordinal).ThenBy(p => p.Parameters.Length).ToList().AsReadOnly(); + _methodDescriptors = listMethods.OrderBy(p => p.Name, StringComparer.Ordinal).ThenBy(p => p.Parameters.Length).ToList().AsReadOnly(); // Reflection to get the events - eventsDescriptors = + _eventsDescriptors = GetType().GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty(), null)?. GetCustomAttributes(). // Take into account not only the contract constructor, but also the base type constructor for proper FungibleToken events handling. @@ -158,26 +158,25 @@ protected NativeContract() OrderBy(p => p.Order).ToList().AsReadOnly(); // Calculate the initializations forks - usedHardforks = - methodDescriptors.Select(u => u.ActiveIn) - .Concat(methodDescriptors.Select(u => u.DeprecatedIn)) - .Concat(eventsDescriptors.Select(u => u.ActiveIn)) - .Concat(new Hardfork?[] { ActiveIn }) - .Where(u => u is not null) - .OrderBy(u => (byte)u) - .Cast().ToImmutableHashSet(); - - contractsList.Add(this); - contractsDictionary.Add(Hash, this); + _usedHardforks = + _methodDescriptors.Select(u => u.ActiveIn) + .Concat(_methodDescriptors.Select(u => u.DeprecatedIn)) + .Concat(_eventsDescriptors.Select(u => u.ActiveIn)) + .Concat([ActiveIn]) + .Where(u => u is not null) + .OrderBy(u => (byte)u) + .Cast().ToImmutableHashSet(); + s_contractsList.Add(this); + s_contractsDictionary.Add(Hash, this); } /// /// The allowed methods and his offsets. /// /// Hardfork checker - /// Block index + /// Block height. Used to check the hardforks and active methods. /// The . - private NativeContractsCache.CacheEntry GetAllowedMethods(IsHardforkEnabledDelegate hfChecker, uint index) + private NativeContractsCache.CacheEntry GetAllowedMethods(IsHardforkEnabledDelegate hfChecker, uint blockHeight) { Dictionary methods = new(); @@ -185,14 +184,14 @@ private NativeContractsCache.CacheEntry GetAllowedMethods(IsHardforkEnabledDeleg byte[] script; using (ScriptBuilder sb = new()) { - foreach (ContractMethodMetadata method in methodDescriptors.Where(u + foreach (ContractMethodMetadata method in _methodDescriptors.Where(u => // no hardfork is involved u.ActiveIn is null && u.DeprecatedIn is null || // deprecated method hardfork is involved - u.DeprecatedIn is not null && hfChecker(u.DeprecatedIn.Value, index) == false || + u.DeprecatedIn is not null && hfChecker(u.DeprecatedIn.Value, blockHeight) == false || // active method hardfork is involved - u.ActiveIn is not null && hfChecker(u.ActiveIn.Value, index)) + u.ActiveIn is not null && hfChecker(u.ActiveIn.Value, blockHeight)) ) { method.Descriptor.Offset = sb.Length; @@ -204,35 +203,35 @@ u.ActiveIn is null && u.DeprecatedIn is null || script = sb.ToArray(); } - return new NativeContractsCache.CacheEntry() { Methods = methods, Script = script }; + return new NativeContractsCache.CacheEntry { Methods = methods, Script = script }; } /// /// The of the native contract. /// /// The where the HardForks are configured. - /// Block index + /// Block index /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ContractState GetContractState(ProtocolSettings settings, uint index) => GetContractState(settings.IsHardforkEnabled, index); + public ContractState GetContractState(ProtocolSettings settings, uint blockHeight) => GetContractState(settings.IsHardforkEnabled, blockHeight); /// /// The of the native contract. /// /// Hardfork checker - /// Block index + /// Block height. Used to check hardforks and active methods. /// The . - public ContractState GetContractState(IsHardforkEnabledDelegate hfChecker, uint index) + public ContractState GetContractState(IsHardforkEnabledDelegate hfChecker, uint blockHeight) { // Get allowed methods and nef script - var allowedMethods = GetAllowedMethods(hfChecker, index); + var allowedMethods = GetAllowedMethods(hfChecker, blockHeight); // Compose nef file var nef = new NefFile() { Compiler = "neo-core-v3.0", Source = string.Empty, - Tokens = Array.Empty(), + Tokens = [], Script = allowedMethods.Script }; nef.CheckSum = NefFile.ComputeChecksum(nef); @@ -241,17 +240,17 @@ public ContractState GetContractState(IsHardforkEnabledDelegate hfChecker, uint var manifest = new ContractManifest() { Name = Name, - Groups = Array.Empty(), - SupportedStandards = Array.Empty(), - Abi = new ContractAbi() + Groups = [], + SupportedStandards = [], + Abi = new ContractAbi { - Events = eventsDescriptors - .Where(u => u.ActiveIn is null || hfChecker(u.ActiveIn.Value, index)) + Events = _eventsDescriptors + .Where(u => u.ActiveIn is null || hfChecker(u.ActiveIn.Value, blockHeight)) .Select(p => p.Descriptor).ToArray(), Methods = allowedMethods.Methods.Values .Select(p => p.Descriptor).ToArray() }, - Permissions = new[] { ContractPermission.DefaultPermission }, + Permissions = [ContractPermission.DefaultPermission], Trusts = WildcardContainer.Create(), Extra = null }; @@ -282,7 +281,7 @@ internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardf var hfs = new List(); // If is in the hardfork height, add them to return array - foreach (var hf in usedHardforks) + foreach (var hf in _usedHardforks) { if (!settings.Hardforks.TryGetValue(hf, out var activeIn)) { @@ -319,9 +318,9 @@ internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardf /// Is the native contract active /// /// The where the HardForks are configured. - /// Block index + /// Block height /// True if the native contract is active - internal bool IsActive(ProtocolSettings settings, uint index) + internal bool IsActive(ProtocolSettings settings, uint blockHeight) { if (ActiveIn is null) return true; @@ -331,7 +330,7 @@ internal bool IsActive(ProtocolSettings settings, uint index) activeIn = 0; } - return activeIn <= index; + return activeIn <= blockHeight; } /// @@ -357,7 +356,7 @@ private protected KeyBuilder CreateStorageKey(byte prefix) /// The native contract with the specified hash. public static NativeContract GetContract(UInt160 hash) { - contractsDictionary.TryGetValue(hash, out var contract); + s_contractsDictionary.TryGetValue(hash, out var contract); return contract; } @@ -380,7 +379,8 @@ internal async void Invoke(ApplicationEngine engine, byte version) ExecutionContextState state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); - engine.AddGas(method.CpuFee * engine.ExecFeeFactor + method.StorageFee * engine.StoragePrice); + // In the unit of datoshi, 1 datoshi = 1e-8 GAS + engine.AddFee(method.CpuFee * engine.ExecFeeFactor + method.StorageFee * engine.StoragePrice); List parameters = new(); if (method.NeedApplicationEngine) parameters.Add(engine); if (method.NeedSnapshot) parameters.Add(engine.Snapshot); @@ -414,7 +414,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) /// if the contract is native; otherwise, . public static bool IsNative(UInt160 hash) { - return contractsDictionary.ContainsKey(hash); + return s_contractsDictionary.ContainsKey(hash); } internal virtual ContractTask InitializeAsync(ApplicationEngine engine, Hardfork? hardFork) diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 1fbf07204e..99ecd41e29 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -106,7 +106,8 @@ private GasDistribution DistributeGas(ApplicationEngine engine, UInt160 account, // PersistingBlock is null when running under the debugger if (engine.PersistingBlock is null) return null; - BigInteger gas = CalculateBonus(engine.Snapshot, state, engine.PersistingBlock.Index); + // In the unit of datoshi, 1 datoshi = 1e-8 GAS + BigInteger datoshi = CalculateBonus(engine.Snapshot, state, engine.PersistingBlock.Index); state.BalanceHeight = engine.PersistingBlock.Index; if (state.VoteTo is not null) { @@ -114,11 +115,11 @@ private GasDistribution DistributeGas(ApplicationEngine engine, UInt160 account, var latestGasPerVote = engine.Snapshot.TryGet(keyLastest) ?? BigInteger.Zero; state.LastGasPerVote = latestGasPerVote; } - if (gas == 0) return null; + if (datoshi == 0) return null; return new GasDistribution { Account = account, - Amount = gas + Amount = datoshi }; } @@ -130,6 +131,7 @@ private BigInteger CalculateBonus(DataCache snapshot, NeoAccountState state, uin var expectEnd = Ledger.CurrentIndex(snapshot) + 1; if (expectEnd != end) throw new ArgumentOutOfRangeException(nameof(end)); if (state.BalanceHeight >= end) return BigInteger.Zero; + // In the unit of datoshi, 1 datoshi = 1e-8 GAS BigInteger neoHolderReward = CalculateNeoHolderReward(snapshot, state.Balance, state.BalanceHeight, end); if (state.VoteTo is null) return neoHolderReward; @@ -142,6 +144,7 @@ private BigInteger CalculateBonus(DataCache snapshot, NeoAccountState state, uin private BigInteger CalculateNeoHolderReward(DataCache snapshot, BigInteger value, uint start, uint end) { + // In the unit of datoshi, 1 GAS = 10^8 datoshi BigInteger sum = 0; foreach (var (index, gasPerBlock) in GetSortedGasRecords(snapshot, end - 1)) { @@ -295,6 +298,7 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetRegisterPrice(DataCache snapshot) { + // In the unit of datoshi, 1 datoshi = 1e-8 GAS return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_RegisterPrice)]; } @@ -327,7 +331,8 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; - engine.AddGas(GetRegisterPrice(engine.Snapshot)); + // In the unit of datoshi, 1 datoshi = 1e-8 GAS + engine.AddFee(GetRegisterPrice(engine.Snapshot)); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable(); diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs index b391518733..13a7264660 100644 --- a/src/Neo/SmartContract/Native/OracleContract.cs +++ b/src/Neo/SmartContract/Native/OracleContract.cs @@ -63,7 +63,7 @@ private void SetPrice(ApplicationEngine engine, long price) /// Gets the price for an Oracle request. /// /// The snapshot used to read data. - /// The price for an Oracle request. + /// The price for an Oracle request, in the unit of datoshi, 1 datoshi = 1e-8 GAS. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetPrice(DataCache snapshot) { @@ -184,7 +184,7 @@ internal override async ContractTask PostPersistAsync(ApplicationEngine engine) } [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] - private async ContractTask Request(ApplicationEngine engine, string url, string filter, string callback, StackItem userData, long gasForResponse) + private async ContractTask Request(ApplicationEngine engine, string url, string filter, string callback, StackItem userData, long gasForResponse /* In the unit of datoshi, 1 datoshi = 1e-8 GAS */) { //Check the arguments if (Utility.StrictUTF8.GetByteCount(url) > MaxUrlLength @@ -193,10 +193,10 @@ private async ContractTask Request(ApplicationEngine engine, string url, string || gasForResponse < 0_10000000) throw new ArgumentException(); - engine.AddGas(GetPrice(engine.Snapshot)); + engine.AddFee(GetPrice(engine.Snapshot)); //Mint gas for the response - engine.AddGas(gasForResponse); + engine.AddFee(gasForResponse); await GAS.Mint(engine, Hash, gasForResponse, false); //Increase the request id diff --git a/src/Neo/SmartContract/Native/PolicyContract.cs b/src/Neo/SmartContract/Native/PolicyContract.cs index aea3a3ab06..adeb2f1c19 100644 --- a/src/Neo/SmartContract/Native/PolicyContract.cs +++ b/src/Neo/SmartContract/Native/PolicyContract.cs @@ -35,6 +35,7 @@ public sealed class PolicyContract : NativeContract /// /// The default network fee per byte of transactions. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS /// public const uint DefaultFeePerByte = 1000; diff --git a/src/Neo/SmartContract/NotifyEventArgs.cs b/src/Neo/SmartContract/NotifyEventArgs.cs index 93c124ea88..257efb3a66 100644 --- a/src/Neo/SmartContract/NotifyEventArgs.cs +++ b/src/Neo/SmartContract/NotifyEventArgs.cs @@ -66,11 +66,31 @@ public void FromStackItem(StackItem stackItem) public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Array(referenceCounter) + { + ScriptHash.ToArray(), + EventName, + State + }; + } + + public StackItem ToStackItem(ReferenceCounter referenceCounter, ApplicationEngine engine) + { + if (engine.IsHardforkEnabled(Hardfork.HF_Domovoi)) { - ScriptHash.ToArray(), - EventName, - State - }; + return new Array(referenceCounter) + { + ScriptHash.ToArray(), + EventName, + State.OnStack ? State : State.DeepCopy(true) + }; + } + + return new Array(referenceCounter) + { + ScriptHash.ToArray(), + EventName, + State + }; } } } diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 7589ae949a..1273bafc50 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -80,6 +80,7 @@ internal static byte[] XOR(byte[] x, byte[] y) /// /// Calculates the network fee for the specified transaction. + /// In the unit of datoshi, 1 datoshi = 1e-8 GAS /// /// The transaction to calculate. /// The snapshot used to read data. @@ -119,7 +120,7 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, var contract = NativeContract.ContractManagement.GetContract(snapshot, hash); if (contract is null) throw new ArgumentException($"The smart contract or address {hash} is not found"); - var md = contract.Manifest.Abi.GetMethod("verify", -1); + var md = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount); if (md is null) throw new ArgumentException($"The smart contract {contract.Hash} haven't got verify method"); if (md.ReturnType != ContractParameterType.Boolean) @@ -138,9 +139,9 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); if (!engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.Hash} returns false."); - maxExecutionCost -= engine.GasConsumed; + maxExecutionCost -= engine.FeeConsumed; if (maxExecutionCost <= 0) throw new InvalidOperationException("Insufficient GAS."); - networkFee += engine.GasConsumed; + networkFee += engine.FeeConsumed; } else if (IsSignatureContract(witnessScript)) { diff --git a/src/Neo/Wallets/NEP6/NEP6Wallet.cs b/src/Neo/Wallets/NEP6/NEP6Wallet.cs index cede8e0efa..17a59fc830 100644 --- a/src/Neo/Wallets/NEP6/NEP6Wallet.cs +++ b/src/Neo/Wallets/NEP6/NEP6Wallet.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; @@ -223,6 +224,10 @@ public override IEnumerable GetAccounts() public override WalletAccount Import(X509Certificate2 cert) { + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + throw new PlatformNotSupportedException("Importing certificates is not supported on macOS."); + } KeyPair key; using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) { diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 761b0b1999..aca30b008f 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; @@ -412,6 +413,10 @@ private static Signer[] GetSigners(UInt160 sender, Signer[] cosigners) /// The imported account. public virtual WalletAccount Import(X509Certificate2 cert) { + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + throw new PlatformNotSupportedException("Importing certificates is not supported on macOS."); + } byte[] privateKey; using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) { @@ -535,7 +540,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, /// The sender of the transaction. /// The cosigners to be added to the transaction. /// The attributes to be added to the transaction. - /// The maximum gas that can be spent to execute the script. + /// The maximum gas that can be spent to execute the script, in the unit of datoshi, 1 datoshi = 1e-8 GAS. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160 sender = null, Signer[] cosigners = null, TransactionAttribute[] attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) @@ -575,7 +580,7 @@ private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory scr { throw new InvalidOperationException($"Failed execution for '{Convert.ToBase64String(script.Span)}'", engine.FaultException); } - tx.SystemFee = engine.GasConsumed; + tx.SystemFee = engine.FeeConsumed; } tx.NetworkFee = tx.CalculateNetworkFee(snapshot, ProtocolSettings, (a) => GetAccount(a)?.Contract?.Script, maxGas); diff --git a/src/Plugins/ApplicationLogs/ApplicationLogs.csproj b/src/Plugins/ApplicationLogs/ApplicationLogs.csproj index 89eea3b1bb..4529b946af 100644 --- a/src/Plugins/ApplicationLogs/ApplicationLogs.csproj +++ b/src/Plugins/ApplicationLogs/ApplicationLogs.csproj @@ -4,6 +4,7 @@ Neo.Plugins.ApplicationLogs Neo.Plugins enable + $(SolutionDir)/bin/$(PackageId) @@ -18,4 +19,4 @@ PreserveNewest - \ No newline at end of file + diff --git a/src/Plugins/ApplicationLogs/LogReader.cs b/src/Plugins/ApplicationLogs/LogReader.cs index 4de4237acb..6a8682ab5e 100644 --- a/src/Plugins/ApplicationLogs/LogReader.cs +++ b/src/Plugins/ApplicationLogs/LogReader.cs @@ -9,21 +9,21 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using ApplicationLogs.Store; -using ApplicationLogs.Store.Models; using Neo.ConsoleService; -using Neo.IO; using Neo.Json; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.ApplicationLogs.Store; +using Neo.Plugins.ApplicationLogs.Store.Models; +using Neo.Plugins.RpcServer; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; using System.Numerics; using static System.IO.Path; -namespace Neo.Plugins +namespace Neo.Plugins.ApplicationLogs { public class LogReader : Plugin { diff --git a/src/Plugins/ApplicationLogs/Settings.cs b/src/Plugins/ApplicationLogs/Settings.cs index 1e425f664b..8f2a0da1e1 100644 --- a/src/Plugins/ApplicationLogs/Settings.cs +++ b/src/Plugins/ApplicationLogs/Settings.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Configuration; -namespace Neo.Plugins +namespace Neo.Plugins.ApplicationLogs { internal class Settings { diff --git a/src/Plugins/ApplicationLogs/Store/LogStorageStore.cs b/src/Plugins/ApplicationLogs/Store/LogStorageStore.cs index aa0357ffb2..147a80034b 100644 --- a/src/Plugins/ApplicationLogs/Store/LogStorageStore.cs +++ b/src/Plugins/ApplicationLogs/Store/LogStorageStore.cs @@ -9,17 +9,14 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using ApplicationLogs.Store.States; -using Neo; using Neo.IO; using Neo.Persistence; -using Neo.Plugins; -using Neo.Plugins.Store.States; +using Neo.Plugins.ApplicationLogs.Store.States; using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; -namespace ApplicationLogs.Store +namespace Neo.Plugins.ApplicationLogs.Store { public sealed class LogStorageStore : IDisposable { @@ -162,7 +159,7 @@ public Guid PutStackItemState(StackItem stackItem) { _snapshot.Put(key, BinarySerializer.Serialize(stackItem, ExecutionEngineLimits.Default with { MaxItemSize = (uint)Settings.Default.MaxStackSize })); } - catch (NotSupportedException) + catch { _snapshot.Put(key, BinarySerializer.Serialize(StackItem.Null, ExecutionEngineLimits.Default with { MaxItemSize = (uint)Settings.Default.MaxStackSize })); } diff --git a/src/Plugins/ApplicationLogs/Store/Models/ApplicationEngineLogModel.cs b/src/Plugins/ApplicationLogs/Store/Models/ApplicationEngineLogModel.cs index 9836db7146..edc85b1da6 100644 --- a/src/Plugins/ApplicationLogs/Store/Models/ApplicationEngineLogModel.cs +++ b/src/Plugins/ApplicationLogs/Store/Models/ApplicationEngineLogModel.cs @@ -9,9 +9,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.Plugins.Store.States; +using Neo.Plugins.ApplicationLogs.Store.States; -namespace Neo.Plugins.Store.Models +namespace Neo.Plugins.ApplicationLogs.Store.Models { public class ApplicationEngineLogModel { diff --git a/src/Plugins/ApplicationLogs/Store/Models/BlockchainEventModel.cs b/src/Plugins/ApplicationLogs/Store/Models/BlockchainEventModel.cs index a882ff1a8c..b067d02f9d 100644 --- a/src/Plugins/ApplicationLogs/Store/Models/BlockchainEventModel.cs +++ b/src/Plugins/ApplicationLogs/Store/Models/BlockchainEventModel.cs @@ -9,11 +9,10 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using ApplicationLogs.Store.States; -using Neo; +using Neo.Plugins.ApplicationLogs.Store.States; using Neo.VM.Types; -namespace ApplicationLogs.Store.Models +namespace Neo.Plugins.ApplicationLogs.Store.Models { public class BlockchainEventModel { diff --git a/src/Plugins/ApplicationLogs/Store/Models/BlockchainExecutionModel.cs b/src/Plugins/ApplicationLogs/Store/Models/BlockchainExecutionModel.cs index 19a3de5749..e8ee0fc180 100644 --- a/src/Plugins/ApplicationLogs/Store/Models/BlockchainExecutionModel.cs +++ b/src/Plugins/ApplicationLogs/Store/Models/BlockchainExecutionModel.cs @@ -9,13 +9,12 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using ApplicationLogs.Store.States; -using Neo.Plugins.Store.Models; +using Neo.Plugins.ApplicationLogs.Store.States; using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; -namespace ApplicationLogs.Store.Models +namespace Neo.Plugins.ApplicationLogs.Store.Models { public class BlockchainExecutionModel { diff --git a/src/Plugins/ApplicationLogs/Store/NeoStore.cs b/src/Plugins/ApplicationLogs/Store/NeoStore.cs index 496502869b..bc61a9b03c 100644 --- a/src/Plugins/ApplicationLogs/Store/NeoStore.cs +++ b/src/Plugins/ApplicationLogs/Store/NeoStore.cs @@ -9,18 +9,15 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using ApplicationLogs.Store.Models; -using ApplicationLogs.Store.States; -using Neo; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; -using Neo.Plugins.Store.Models; -using Neo.Plugins.Store.States; +using Neo.Plugins.ApplicationLogs.Store.Models; +using Neo.Plugins.ApplicationLogs.Store.States; using Neo.SmartContract; using Neo.VM.Types; -namespace ApplicationLogs.Store +namespace Neo.Plugins.ApplicationLogs.Store { public sealed class NeoStore : IDisposable { diff --git a/src/Plugins/ApplicationLogs/Store/States/BlockLogState.cs b/src/Plugins/ApplicationLogs/Store/States/BlockLogState.cs index dcbb58b6e6..54369a672a 100644 --- a/src/Plugins/ApplicationLogs/Store/States/BlockLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/BlockLogState.cs @@ -12,7 +12,7 @@ using Neo; using Neo.IO; -namespace ApplicationLogs.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class BlockLogState : ISerializable, IEquatable { diff --git a/src/Plugins/ApplicationLogs/Store/States/ContractLogState.cs b/src/Plugins/ApplicationLogs/Store/States/ContractLogState.cs index 0987e86e67..011886f67c 100644 --- a/src/Plugins/ApplicationLogs/Store/States/ContractLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/ContractLogState.cs @@ -14,7 +14,7 @@ using Neo.Ledger; using Neo.SmartContract; -namespace ApplicationLogs.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class ContractLogState : NotifyLogState, IEquatable { diff --git a/src/Plugins/ApplicationLogs/Store/States/EngineLogState.cs b/src/Plugins/ApplicationLogs/Store/States/EngineLogState.cs index 8b07855253..96f9041aaf 100644 --- a/src/Plugins/ApplicationLogs/Store/States/EngineLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/EngineLogState.cs @@ -11,7 +11,7 @@ using Neo.IO; -namespace Neo.Plugins.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class EngineLogState : ISerializable, IEquatable { diff --git a/src/Plugins/ApplicationLogs/Store/States/ExecutionLogState.cs b/src/Plugins/ApplicationLogs/Store/States/ExecutionLogState.cs index 44f8a74b49..210ac36283 100644 --- a/src/Plugins/ApplicationLogs/Store/States/ExecutionLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/ExecutionLogState.cs @@ -13,7 +13,7 @@ using Neo.Ledger; using Neo.VM; -namespace ApplicationLogs.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class ExecutionLogState : ISerializable, IEquatable { diff --git a/src/Plugins/ApplicationLogs/Store/States/NotifyLogState.cs b/src/Plugins/ApplicationLogs/Store/States/NotifyLogState.cs index 20fbd9e456..70b53268e5 100644 --- a/src/Plugins/ApplicationLogs/Store/States/NotifyLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/NotifyLogState.cs @@ -13,7 +13,7 @@ using Neo.IO; using Neo.SmartContract; -namespace ApplicationLogs.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class NotifyLogState : ISerializable, IEquatable { diff --git a/src/Plugins/ApplicationLogs/Store/States/TransactionEngineLogState.cs b/src/Plugins/ApplicationLogs/Store/States/TransactionEngineLogState.cs index 8b32867b66..9417f984e2 100644 --- a/src/Plugins/ApplicationLogs/Store/States/TransactionEngineLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/TransactionEngineLogState.cs @@ -11,7 +11,7 @@ using Neo.IO; -namespace Neo.Plugins.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class TransactionEngineLogState : ISerializable, IEquatable { diff --git a/src/Plugins/ApplicationLogs/Store/States/TransactionLogState.cs b/src/Plugins/ApplicationLogs/Store/States/TransactionLogState.cs index b40d3244d0..1667478509 100644 --- a/src/Plugins/ApplicationLogs/Store/States/TransactionLogState.cs +++ b/src/Plugins/ApplicationLogs/Store/States/TransactionLogState.cs @@ -9,10 +9,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo; using Neo.IO; -namespace ApplicationLogs.Store.States +namespace Neo.Plugins.ApplicationLogs.Store.States { public class TransactionLogState : ISerializable, IEquatable { diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.Get.cs index b54b6eca1e..edffc1cb09 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -10,13 +10,12 @@ // modifications are permitted. using Neo.Network.P2P.Payloads; +using Neo.Plugins.DBFTPlugin.Messages; using Neo.SmartContract; -using Neo.Wallets; using System.Linq; using System.Runtime.CompilerServices; -using static Neo.Consensus.RecoveryMessage; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Consensus { partial class ConsensusContext { @@ -33,10 +32,10 @@ public T GetMessage(ExtensiblePayload payload) where T : ConsensusMessage return (T)GetMessage(payload); } - private ChangeViewPayloadCompact GetChangeViewPayloadCompact(ExtensiblePayload payload) + private RecoveryMessage.ChangeViewPayloadCompact GetChangeViewPayloadCompact(ExtensiblePayload payload) { ChangeView message = GetMessage(payload); - return new ChangeViewPayloadCompact + return new RecoveryMessage.ChangeViewPayloadCompact { ValidatorIndex = message.ValidatorIndex, OriginalViewNumber = message.ViewNumber, @@ -45,10 +44,10 @@ private ChangeViewPayloadCompact GetChangeViewPayloadCompact(ExtensiblePayload p }; } - private CommitPayloadCompact GetCommitPayloadCompact(ExtensiblePayload payload) + private RecoveryMessage.CommitPayloadCompact GetCommitPayloadCompact(ExtensiblePayload payload) { Commit message = GetMessage(payload); - return new CommitPayloadCompact + return new RecoveryMessage.CommitPayloadCompact { ViewNumber = message.ViewNumber, ValidatorIndex = message.ValidatorIndex, @@ -57,9 +56,9 @@ private CommitPayloadCompact GetCommitPayloadCompact(ExtensiblePayload payload) }; } - private PreparationPayloadCompact GetPreparationPayloadCompact(ExtensiblePayload payload) + private RecoveryMessage.PreparationPayloadCompact GetPreparationPayloadCompact(ExtensiblePayload payload) { - return new PreparationPayloadCompact + return new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = GetMessage(payload).ValidatorIndex, InvocationScript = payload.Witness.InvocationScript diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index a761cbafb0..ee3b8a7747 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -11,15 +11,16 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.Plugins.DBFTPlugin.Messages; +using Neo.Plugins.DBFTPlugin.Types; using Neo.SmartContract; using Neo.Wallets; using System; using System.Buffers.Binary; using System.Collections.Generic; using System.Linq; -using static Neo.Consensus.RecoveryMessage; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Consensus { partial class ConsensusContext { @@ -153,7 +154,7 @@ public ExtensiblePayload MakeRecoveryMessage() PreparationMessages = PreparationPayloads.Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), CommitMessages = CommitSent ? CommitPayloads.Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) - : new Dictionary() + : new Dictionary() }); } diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs index 35044e4fb8..abd0309783 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusContext.cs @@ -15,6 +15,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.DBFTPlugin.Messages; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -24,7 +25,7 @@ using System.IO; using System.Linq; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Consensus { public partial class ConsensusContext : IDisposable, ISerializable { diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusService.Check.cs index 3b15bcd8fc..c6ba86ee86 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -13,10 +13,12 @@ using Neo.IO; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using Neo.Plugins.DBFTPlugin.Messages; +using Neo.Plugins.DBFTPlugin.Types; using System; using System.Linq; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Consensus { partial class ConsensusService { diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index ecc31f7ba3..3c6ab8e243 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -11,18 +11,17 @@ using Akka.Actor; using Neo.Cryptography; -using Neo.IO; using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using Neo.Plugins.DBFTPlugin.Messages; using Neo.SmartContract; using Neo.SmartContract.Native; -using Neo.Wallets; using System; using System.Collections.Generic; using System.Linq; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Consensus { partial class ConsensusService { diff --git a/src/Plugins/DBFTPlugin/Consensus/ConsensusService.cs b/src/Plugins/DBFTPlugin/Consensus/ConsensusService.cs index 8a6d75e8b9..eb97e7024b 100644 --- a/src/Plugins/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/Plugins/DBFTPlugin/Consensus/ConsensusService.cs @@ -14,13 +14,15 @@ using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using Neo.Plugins.DBFTPlugin.Messages; +using Neo.Plugins.DBFTPlugin.Types; using Neo.Wallets; using System; using System.Collections.Generic; using System.Linq; using static Neo.Ledger.Blockchain; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Consensus { partial class ConsensusService : UntypedActor { diff --git a/src/Plugins/DBFTPlugin/DBFTPlugin.cs b/src/Plugins/DBFTPlugin/DBFTPlugin.cs index 59191d2881..9ca44adc74 100644 --- a/src/Plugins/DBFTPlugin/DBFTPlugin.cs +++ b/src/Plugins/DBFTPlugin/DBFTPlugin.cs @@ -14,9 +14,10 @@ using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.Plugins; +using Neo.Plugins.DBFTPlugin.Consensus; using Neo.Wallets; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin { public class DBFTPlugin : Plugin { diff --git a/src/Plugins/DBFTPlugin/DBFTPlugin.csproj b/src/Plugins/DBFTPlugin/DBFTPlugin.csproj index b04e2e5c4f..68595be53a 100644 --- a/src/Plugins/DBFTPlugin/DBFTPlugin.csproj +++ b/src/Plugins/DBFTPlugin/DBFTPlugin.csproj @@ -4,6 +4,7 @@ net8.0 Neo.Consensus.DBFT Neo.Consensus + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/DBFTPlugin/Messages/ChangeView.cs b/src/Plugins/DBFTPlugin/Messages/ChangeView.cs index e7be40075f..84f681f499 100644 --- a/src/Plugins/DBFTPlugin/Messages/ChangeView.cs +++ b/src/Plugins/DBFTPlugin/Messages/ChangeView.cs @@ -10,9 +10,10 @@ // modifications are permitted. using Neo.IO; +using Neo.Plugins.DBFTPlugin.Types; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public class ChangeView : ConsensusMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/Commit.cs b/src/Plugins/DBFTPlugin/Messages/Commit.cs index 6e8fe93d87..8f276bb6fe 100644 --- a/src/Plugins/DBFTPlugin/Messages/Commit.cs +++ b/src/Plugins/DBFTPlugin/Messages/Commit.cs @@ -10,10 +10,11 @@ // modifications are permitted. using Neo.IO; +using Neo.Plugins.DBFTPlugin.Types; using System; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public class Commit : ConsensusMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs b/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs index 4e136a99e5..de030d166d 100644 --- a/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs +++ b/src/Plugins/DBFTPlugin/Messages/ConsensusMessage.cs @@ -10,10 +10,11 @@ // modifications are permitted. using Neo.IO; +using Neo.Plugins.DBFTPlugin.Types; using System; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public abstract class ConsensusMessage : ISerializable { diff --git a/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs b/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs index 2bce609f79..495ccbd726 100644 --- a/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs +++ b/src/Plugins/DBFTPlugin/Messages/PrepareRequest.cs @@ -10,11 +10,12 @@ // modifications are permitted. using Neo.IO; +using Neo.Plugins.DBFTPlugin.Types; using System; using System.IO; using System.Linq; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public class PrepareRequest : ConsensusMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/PrepareResponse.cs b/src/Plugins/DBFTPlugin/Messages/PrepareResponse.cs index 7510ff99bb..b4608ff9af 100644 --- a/src/Plugins/DBFTPlugin/Messages/PrepareResponse.cs +++ b/src/Plugins/DBFTPlugin/Messages/PrepareResponse.cs @@ -10,9 +10,10 @@ // modifications are permitted. using Neo.IO; +using Neo.Plugins.DBFTPlugin.Types; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public class PrepareResponse : ConsensusMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.ChangeViewPayloadCompact.cs b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.ChangeViewPayloadCompact.cs index 6a7734e569..2d7283cd22 100644 --- a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.ChangeViewPayloadCompact.cs +++ b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.ChangeViewPayloadCompact.cs @@ -13,7 +13,7 @@ using System; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { partial class RecoveryMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.CommitPayloadCompact.cs b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.CommitPayloadCompact.cs index 2dfa16597a..6d3880f3c0 100644 --- a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.CommitPayloadCompact.cs +++ b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.CommitPayloadCompact.cs @@ -13,7 +13,7 @@ using System; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { partial class RecoveryMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreparationPayloadCompact.cs b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreparationPayloadCompact.cs index 80b2a48b6f..8fae1596ef 100644 --- a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreparationPayloadCompact.cs +++ b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreparationPayloadCompact.cs @@ -13,7 +13,7 @@ using System; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { partial class RecoveryMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index fc688d6a1f..2de33470ea 100644 --- a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -11,12 +11,14 @@ using Neo.IO; using Neo.Network.P2P.Payloads; +using Neo.Plugins.DBFTPlugin.Consensus; +using Neo.Plugins.DBFTPlugin.Types; using System; using System.Collections.Generic; using System.IO; using System.Linq; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public partial class RecoveryMessage : ConsensusMessage { diff --git a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryRequest.cs b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryRequest.cs index 84cd381add..2872d28e26 100644 --- a/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryRequest.cs +++ b/src/Plugins/DBFTPlugin/Messages/RecoveryMessage/RecoveryRequest.cs @@ -10,9 +10,10 @@ // modifications are permitted. using Neo.IO; +using Neo.Plugins.DBFTPlugin.Types; using System.IO; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Messages { public class RecoveryRequest : ConsensusMessage { diff --git a/src/Plugins/DBFTPlugin/Settings.cs b/src/Plugins/DBFTPlugin/Settings.cs index d0ecbb63fd..28ad21f37a 100644 --- a/src/Plugins/DBFTPlugin/Settings.cs +++ b/src/Plugins/DBFTPlugin/Settings.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Configuration; -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin { public class Settings { diff --git a/src/Plugins/DBFTPlugin/Types/ChangeViewReason.cs b/src/Plugins/DBFTPlugin/Types/ChangeViewReason.cs index 4c0a3c1100..5d9e55ffeb 100644 --- a/src/Plugins/DBFTPlugin/Types/ChangeViewReason.cs +++ b/src/Plugins/DBFTPlugin/Types/ChangeViewReason.cs @@ -9,7 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Types { public enum ChangeViewReason : byte { diff --git a/src/Plugins/DBFTPlugin/Types/ConsensusMessageType.cs b/src/Plugins/DBFTPlugin/Types/ConsensusMessageType.cs index f325133f08..81636e94c1 100644 --- a/src/Plugins/DBFTPlugin/Types/ConsensusMessageType.cs +++ b/src/Plugins/DBFTPlugin/Types/ConsensusMessageType.cs @@ -9,7 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -namespace Neo.Consensus +namespace Neo.Plugins.DBFTPlugin.Types { public enum ConsensusMessageType : byte { diff --git a/src/Plugins/Directory.Build.props b/src/Plugins/Directory.Build.props index f7bcef093b..72e96f0300 100644 --- a/src/Plugins/Directory.Build.props +++ b/src/Plugins/Directory.Build.props @@ -9,7 +9,7 @@ - + diff --git a/src/Plugins/LevelDBStore/LevelDBStore.csproj b/src/Plugins/LevelDBStore/LevelDBStore.csproj index ba82156b18..ef605a7afe 100644 --- a/src/Plugins/LevelDBStore/LevelDBStore.csproj +++ b/src/Plugins/LevelDBStore/LevelDBStore.csproj @@ -5,6 +5,7 @@ Neo.Plugins.Storage.LevelDBStore Neo.Plugins.Storage true + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/MPTTrie/MPTTrie.csproj b/src/Plugins/MPTTrie/MPTTrie.csproj index a2c3377a16..ef9e45cc51 100644 --- a/src/Plugins/MPTTrie/MPTTrie.csproj +++ b/src/Plugins/MPTTrie/MPTTrie.csproj @@ -5,6 +5,7 @@ Neo.Cryptography.MPT Neo.Cryptography true + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/OracleService/Helper.cs b/src/Plugins/OracleService/Helper.cs index 35611e8698..a4711b848e 100644 --- a/src/Plugins/OracleService/Helper.cs +++ b/src/Plugins/OracleService/Helper.cs @@ -12,7 +12,7 @@ using System.Linq; using System.Net; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService { static class Helper { diff --git a/src/Plugins/OracleService/OracleService.cs b/src/Plugins/OracleService/OracleService.cs index 637c06712f..e9787b3d4c 100644 --- a/src/Plugins/OracleService/OracleService.cs +++ b/src/Plugins/OracleService/OracleService.cs @@ -20,6 +20,7 @@ using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.RpcServer; using Neo.SmartContract; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; @@ -34,7 +35,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService { public class OracleService : Plugin { @@ -427,10 +428,10 @@ public static Transaction CreateResponseTx(DataCache snapshot, OracleRequest req var oracleContract = NativeContract.ContractManagement.GetContract(snapshot, NativeContract.Oracle.Hash); var engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: settings); - ContractMethodDescriptor md = oracleContract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor md = oracleContract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount); engine.LoadContract(oracleContract, md, CallFlags.None); if (engine.Execute() != VMState.HALT) return null; - tx.NetworkFee += engine.GasConsumed; + tx.NetworkFee += engine.FeeConsumed; var executionFactor = NativeContract.Policy.GetExecFeeFactor(snapshot); var networkFee = executionFactor * SmartContract.Helper.MultiSignatureContractCost(m, n); diff --git a/src/Plugins/OracleService/OracleService.csproj b/src/Plugins/OracleService/OracleService.csproj index 48ca5f3808..1fa5c5602f 100644 --- a/src/Plugins/OracleService/OracleService.csproj +++ b/src/Plugins/OracleService/OracleService.csproj @@ -3,6 +3,7 @@ net8.0 Neo.Plugins.OracleService + $(SolutionDir)/bin/$(PackageId) @@ -23,4 +24,4 @@ - \ No newline at end of file + diff --git a/src/Plugins/OracleService/Protocols/IOracleProtocol.cs b/src/Plugins/OracleService/Protocols/IOracleProtocol.cs index 3532a69454..d8b84660ee 100644 --- a/src/Plugins/OracleService/Protocols/IOracleProtocol.cs +++ b/src/Plugins/OracleService/Protocols/IOracleProtocol.cs @@ -14,7 +14,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService { interface IOracleProtocol : IDisposable { diff --git a/src/Plugins/OracleService/Protocols/OracleHttpsProtocol.cs b/src/Plugins/OracleService/Protocols/OracleHttpsProtocol.cs index 29d3eedc43..a825f5e60f 100644 --- a/src/Plugins/OracleService/Protocols/OracleHttpsProtocol.cs +++ b/src/Plugins/OracleService/Protocols/OracleHttpsProtocol.cs @@ -20,7 +20,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService { class OracleHttpsProtocol : IOracleProtocol { diff --git a/src/Plugins/OracleService/Protocols/OracleNeoFSProtocol.cs b/src/Plugins/OracleService/Protocols/OracleNeoFSProtocol.cs index 2bf92fa8f4..de0cbd8044 100644 --- a/src/Plugins/OracleService/Protocols/OracleNeoFSProtocol.cs +++ b/src/Plugins/OracleService/Protocols/OracleNeoFSProtocol.cs @@ -24,7 +24,7 @@ using Object = Neo.FileStorage.API.Object.Object; using Range = Neo.FileStorage.API.Object.Range; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService { class OracleNeoFSProtocol : IOracleProtocol { diff --git a/src/Plugins/OracleService/Settings.cs b/src/Plugins/OracleService/Settings.cs index c66010cb5f..952ea0c27b 100644 --- a/src/Plugins/OracleService/Settings.cs +++ b/src/Plugins/OracleService/Settings.cs @@ -13,7 +13,7 @@ using System; using System.Linq; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService { class HttpsSettings { diff --git a/src/Plugins/RocksDBStore/RocksDBStore.csproj b/src/Plugins/RocksDBStore/RocksDBStore.csproj index 57037c68cf..441b17306e 100644 --- a/src/Plugins/RocksDBStore/RocksDBStore.csproj +++ b/src/Plugins/RocksDBStore/RocksDBStore.csproj @@ -4,6 +4,7 @@ net8.0 Neo.Plugins.Storage.RocksDBStore Neo.Plugins.Storage + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/RpcClient/RpcClient.csproj b/src/Plugins/RpcClient/RpcClient.csproj index cc634337d5..c43c71ef8a 100644 --- a/src/Plugins/RpcClient/RpcClient.csproj +++ b/src/Plugins/RpcClient/RpcClient.csproj @@ -4,6 +4,7 @@ net8.0 Neo.Network.RPC.RpcClient Neo.Network.RPC + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/RpcServer/Diagnostic.cs b/src/Plugins/RpcServer/Diagnostic.cs index a8cba4af9a..7363bc852c 100644 --- a/src/Plugins/RpcServer/Diagnostic.cs +++ b/src/Plugins/RpcServer/Diagnostic.cs @@ -12,7 +12,7 @@ using Neo.SmartContract; using Neo.VM; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { class Diagnostic : IDiagnostic { diff --git a/src/Plugins/RpcServer/Result.cs b/src/Plugins/RpcServer/Result.cs index 0ead2482cd..9c7ace227c 100644 --- a/src/Plugins/RpcServer/Result.cs +++ b/src/Plugins/RpcServer/Result.cs @@ -10,7 +10,7 @@ // modifications are permitted. using System; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { public static class Result { diff --git a/src/Plugins/RpcServer/RpcError.cs b/src/Plugins/RpcServer/RpcError.cs index 7130540183..667a3906d4 100644 --- a/src/Plugins/RpcServer/RpcError.cs +++ b/src/Plugins/RpcServer/RpcError.cs @@ -11,7 +11,7 @@ using Neo.Json; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { public class RpcError { diff --git a/src/Plugins/RpcServer/RpcErrorFactory.cs b/src/Plugins/RpcServer/RpcErrorFactory.cs index 328ba02f61..3d2ac7c9a5 100644 --- a/src/Plugins/RpcServer/RpcErrorFactory.cs +++ b/src/Plugins/RpcServer/RpcErrorFactory.cs @@ -11,7 +11,7 @@ using Neo.Cryptography.ECC; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { public static class RpcErrorFactory { diff --git a/src/Plugins/RpcServer/RpcException.cs b/src/Plugins/RpcServer/RpcException.cs index 5c7b5675a1..ab47901b6d 100644 --- a/src/Plugins/RpcServer/RpcException.cs +++ b/src/Plugins/RpcServer/RpcException.cs @@ -11,7 +11,7 @@ using System; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { public class RpcException : Exception { diff --git a/src/Plugins/RpcServer/RpcMethodAttribute.cs b/src/Plugins/RpcServer/RpcMethodAttribute.cs index 89edccdd5a..743530ca83 100644 --- a/src/Plugins/RpcServer/RpcMethodAttribute.cs +++ b/src/Plugins/RpcServer/RpcMethodAttribute.cs @@ -11,7 +11,7 @@ using System; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class RpcMethodAttribute : Attribute diff --git a/src/Plugins/RpcServer/RpcServer.Blockchain.cs b/src/Plugins/RpcServer/RpcServer.Blockchain.cs index a4fda6e738..1c8eecb99f 100644 --- a/src/Plugins/RpcServer/RpcServer.Blockchain.cs +++ b/src/Plugins/RpcServer/RpcServer.Blockchain.cs @@ -20,7 +20,7 @@ using System.Collections.Generic; using System.Linq; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { partial class RpcServer { @@ -61,7 +61,7 @@ protected virtual JToken GetBlock(JArray _params) } [RpcMethod] - protected virtual JToken GetBlockHeaderCount(JArray _params) + internal virtual JToken GetBlockHeaderCount(JArray _params) { return (system.HeaderCache.Last?.Index ?? NativeContract.Ledger.CurrentIndex(system.StoreView)) + 1; } @@ -119,15 +119,13 @@ protected virtual JToken GetContractState(JArray _params) { if (int.TryParse(_params[0].AsString(), out int contractId)) { - var contracts = NativeContract.ContractManagement.GetContractById(system.StoreView, contractId); - return contracts?.ToJson().NotNull_Or(RpcError.UnknownContract); - } - else - { - UInt160 script_hash = ToScriptHash(_params[0].AsString()); - ContractState contract = NativeContract.ContractManagement.GetContract(system.StoreView, script_hash); - return contract?.ToJson().NotNull_Or(RpcError.UnknownContract); + var contractState = NativeContract.ContractManagement.GetContractById(system.StoreView, contractId); + return contractState.NotNull_Or(RpcError.UnknownContract).ToJson(); } + + var scriptHash = ToScriptHash(_params[0].AsString()); + var contract = NativeContract.ContractManagement.GetContract(system.StoreView, scriptHash); + return contract.NotNull_Or(RpcError.UnknownContract).ToJson(); } private static UInt160 ToScriptHash(string keyword) diff --git a/src/Plugins/RpcServer/RpcServer.Node.cs b/src/Plugins/RpcServer/RpcServer.Node.cs index c455100802..79a8884a0f 100644 --- a/src/Plugins/RpcServer/RpcServer.Node.cs +++ b/src/Plugins/RpcServer/RpcServer.Node.cs @@ -19,7 +19,7 @@ using System.Linq; using static Neo.Ledger.Blockchain; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { partial class RpcServer { diff --git a/src/Plugins/RpcServer/RpcServer.SmartContract.cs b/src/Plugins/RpcServer/RpcServer.SmartContract.cs index 92ea7ff62c..2fe49d4965 100644 --- a/src/Plugins/RpcServer/RpcServer.SmartContract.cs +++ b/src/Plugins/RpcServer/RpcServer.SmartContract.cs @@ -26,7 +26,7 @@ using System.Threading; using Array = System.Array; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { partial class RpcServer { @@ -75,7 +75,8 @@ private JObject GetInvokeResult(byte[] script, Signer[] signers = null, Witness[ { json["script"] = Convert.ToBase64String(script); json["state"] = session.Engine.State; - json["gasconsumed"] = session.Engine.GasConsumed.ToString(); + // Gas consumed in the unit of datoshi, 1 GAS = 10^8 datoshi + json["gasconsumed"] = session.Engine.FeeConsumed.ToString(); json["exception"] = GetExceptionMessage(session.Engine.FaultException); json["notifications"] = new JArray(session.Engine.Notifications.Select(n => { diff --git a/src/Plugins/RpcServer/RpcServer.Utilities.cs b/src/Plugins/RpcServer/RpcServer.Utilities.cs index f410e01b73..f9b874c824 100644 --- a/src/Plugins/RpcServer/RpcServer.Utilities.cs +++ b/src/Plugins/RpcServer/RpcServer.Utilities.cs @@ -13,7 +13,7 @@ using Neo.Wallets; using System.Linq; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { partial class RpcServer { diff --git a/src/Plugins/RpcServer/RpcServer.Wallet.cs b/src/Plugins/RpcServer/RpcServer.Wallet.cs index 36825b3f82..f1adb277ce 100644 --- a/src/Plugins/RpcServer/RpcServer.Wallet.cs +++ b/src/Plugins/RpcServer/RpcServer.Wallet.cs @@ -25,7 +25,7 @@ using System.Linq; using System.Numerics; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { partial class RpcServer { @@ -95,14 +95,15 @@ protected virtual JToken GetWalletBalance(JArray _params) protected virtual JToken GetWalletUnclaimedGas(JArray _params) { CheckWallet(); - BigInteger gas = BigInteger.Zero; + // Datoshi is the smallest unit of GAS, 1 GAS = 10^8 Datoshi + BigInteger datoshi = BigInteger.Zero; using (var snapshot = system.GetSnapshot()) { uint height = NativeContract.Ledger.CurrentIndex(snapshot) + 1; foreach (UInt160 account in wallet.GetAccounts().Select(p => p.ScriptHash)) - gas += NativeContract.NEO.UnclaimedGas(snapshot, account, height); + datoshi += NativeContract.NEO.UnclaimedGas(snapshot, account, height); } - return gas.ToString(); + return datoshi.ToString(); } [RpcMethod] @@ -355,7 +356,7 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar { using var snapshot = system.GetSnapshot(); var contract = NativeContract.ContractManagement.GetContract(snapshot, scriptHash).NotNull_Or(RpcError.UnknownContract); - var md = contract.Manifest.Abi.GetMethod("verify", -1).NotNull_Or(RpcErrorFactory.InvalidContractVerification(contract.Hash)); + var md = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount).NotNull_Or(RpcErrorFactory.InvalidContractVerification(contract.Hash)); (md.ReturnType == ContractParameterType.Boolean).True_Or(RpcErrorFactory.InvalidContractVerification("The verify method doesn't return boolean value.")); Transaction tx = new() { @@ -381,7 +382,8 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar JObject json = new(); json["script"] = Convert.ToBase64String(invocationScript); json["state"] = engine.Execute(); - json["gasconsumed"] = engine.GasConsumed.ToString(); + // Gas consumed in the unit of datoshi, 1 GAS = 1e8 datoshi + json["gasconsumed"] = engine.FeeConsumed.ToString(); json["exception"] = GetExceptionMessage(engine.FaultException); try { diff --git a/src/Plugins/RpcServer/RpcServer.cs b/src/Plugins/RpcServer/RpcServer.cs index f77c2d1e33..c53f17b860 100644 --- a/src/Plugins/RpcServer/RpcServer.cs +++ b/src/Plugins/RpcServer/RpcServer.cs @@ -29,7 +29,7 @@ using System.Text; using System.Threading.Tasks; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { public partial class RpcServer : IDisposable { @@ -51,7 +51,7 @@ public RpcServer(NeoSystem system, RpcServerSettings settings) Initialize_SmartContract(); } - private bool CheckAuth(HttpContext context) + internal bool CheckAuth(HttpContext context) { if (string.IsNullOrEmpty(settings.RpcUser)) return true; diff --git a/src/Plugins/RpcServer/RpcServer.csproj b/src/Plugins/RpcServer/RpcServer.csproj index ab2d7e6783..3fb7a7bb9a 100644 --- a/src/Plugins/RpcServer/RpcServer.csproj +++ b/src/Plugins/RpcServer/RpcServer.csproj @@ -1,8 +1,9 @@ - + - net8.0 + net8.0 Neo.Plugins.RpcServer + $(SolutionDir)/bin/$(PackageId) @@ -15,4 +16,8 @@ + + + + diff --git a/src/Plugins/RpcServer/RpcServerPlugin.cs b/src/Plugins/RpcServer/RpcServerPlugin.cs index 61d9da4397..c22462d139 100644 --- a/src/Plugins/RpcServer/RpcServerPlugin.cs +++ b/src/Plugins/RpcServer/RpcServerPlugin.cs @@ -12,7 +12,7 @@ using System.Collections.Generic; using System.Linq; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { public class RpcServerPlugin : Plugin { @@ -55,18 +55,18 @@ protected override void OnSystemLoaded(NeoSystem system) $"Example: \"AllowOrigins\": [\"http://{s.BindAddress}:{s.Port}\"]", LogLevel.Info); } - RpcServer server = new(system, s); + RpcServer rpcRpcServer = new(system, s); if (handlers.Remove(s.Network, out var list)) { foreach (var handler in list) { - server.RegisterMethods(handler); + rpcRpcServer.RegisterMethods(handler); } } - server.StartRpcServer(); - servers.TryAdd(s.Network, server); + rpcRpcServer.StartRpcServer(); + servers.TryAdd(s.Network, rpcRpcServer); } public static void RegisterMethods(object handler, uint network) diff --git a/src/Plugins/RpcServer/Session.cs b/src/Plugins/RpcServer/Session.cs index 2b4213c28e..1dd8808dde 100644 --- a/src/Plugins/RpcServer/Session.cs +++ b/src/Plugins/RpcServer/Session.cs @@ -17,7 +17,7 @@ using System; using System.Collections.Generic; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { class Session : IDisposable { @@ -26,7 +26,7 @@ class Session : IDisposable public readonly Dictionary Iterators = new(); public DateTime StartTime; - public Session(NeoSystem system, byte[] script, Signer[] signers, Witness[] witnesses, long gas, Diagnostic diagnostic) + public Session(NeoSystem system, byte[] script, Signer[] signers, Witness[] witnesses, long datoshi, Diagnostic diagnostic) { Random random = new(); Snapshot = system.GetSnapshot(); @@ -40,7 +40,7 @@ public Session(NeoSystem system, byte[] script, Signer[] signers, Witness[] witn Script = script, Witnesses = witnesses }; - Engine = ApplicationEngine.Run(script, Snapshot, container: tx, settings: system.Settings, gas: gas, diagnostic: diagnostic); + Engine = ApplicationEngine.Run(script, Snapshot, container: tx, settings: system.Settings, gas: datoshi, diagnostic: diagnostic); ResetExpiration(); } diff --git a/src/Plugins/RpcServer/Settings.cs b/src/Plugins/RpcServer/Settings.cs index f4aef116c6..ad624d9082 100644 --- a/src/Plugins/RpcServer/Settings.cs +++ b/src/Plugins/RpcServer/Settings.cs @@ -16,7 +16,7 @@ using System.Linq; using System.Net; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { class Settings { @@ -44,7 +44,9 @@ public record RpcServerSettings public string[] AllowOrigins { get; init; } public int KeepAliveTimeout { get; init; } public uint RequestHeadersTimeout { get; init; } + // In the unit of datoshi, 1 GAS = 10^8 datoshi public long MaxGasInvoke { get; init; } + // In the unit of datoshi, 1 GAS = 10^8 datoshi public long MaxFee { get; init; } public int MaxIteratorResultItems { get; init; } public int MaxStackSize { get; init; } diff --git a/src/Plugins/RpcServer/Tree.cs b/src/Plugins/RpcServer/Tree.cs index 77ca1fc2a5..b2d1afc11a 100644 --- a/src/Plugins/RpcServer/Tree.cs +++ b/src/Plugins/RpcServer/Tree.cs @@ -12,7 +12,7 @@ using System; using System.Collections.Generic; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { class Tree { diff --git a/src/Plugins/RpcServer/TreeNode.cs b/src/Plugins/RpcServer/TreeNode.cs index 82785277b6..0ba06a689f 100644 --- a/src/Plugins/RpcServer/TreeNode.cs +++ b/src/Plugins/RpcServer/TreeNode.cs @@ -11,7 +11,7 @@ using System.Collections.Generic; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { class TreeNode { diff --git a/src/Plugins/RpcServer/Utility.cs b/src/Plugins/RpcServer/Utility.cs index 24ccc9248d..1dda8c131c 100644 --- a/src/Plugins/RpcServer/Utility.cs +++ b/src/Plugins/RpcServer/Utility.cs @@ -14,7 +14,7 @@ using Neo.SmartContract.Native; using System.Linq; -namespace Neo.Plugins +namespace Neo.Plugins.RpcServer { static class Utility { diff --git a/src/Plugins/SQLiteWallet/SQLiteWallet.csproj b/src/Plugins/SQLiteWallet/SQLiteWallet.csproj index fb2d3e71b8..4c9029040f 100644 --- a/src/Plugins/SQLiteWallet/SQLiteWallet.csproj +++ b/src/Plugins/SQLiteWallet/SQLiteWallet.csproj @@ -5,6 +5,7 @@ Neo.Wallets.SQLite Neo.Wallets.SQLite enable + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/StateService/StatePlugin.cs b/src/Plugins/StateService/StatePlugin.cs index 36d2c01050..1c28e92193 100644 --- a/src/Plugins/StateService/StatePlugin.cs +++ b/src/Plugins/StateService/StatePlugin.cs @@ -17,6 +17,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.RpcServer; using Neo.Plugins.StateService.Network; using Neo.Plugins.StateService.Storage; using Neo.Plugins.StateService.Verification; diff --git a/src/Plugins/StateService/StateService.csproj b/src/Plugins/StateService/StateService.csproj index b8e395c990..2bf85f1465 100644 --- a/src/Plugins/StateService/StateService.csproj +++ b/src/Plugins/StateService/StateService.csproj @@ -4,6 +4,7 @@ net8.0 Neo.Plugins.StateService true + $(SolutionDir)/bin/$(PackageId) @@ -18,4 +19,4 @@ - \ No newline at end of file + diff --git a/src/Plugins/StatesDumper/PersistActions.cs b/src/Plugins/StatesDumper/PersistActions.cs deleted file mode 100644 index 9c1aa2210c..0000000000 --- a/src/Plugins/StatesDumper/PersistActions.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2015-2024 The Neo Project. -// -// PersistActions.cs file belongs to the neo project and is free -// software distributed under the MIT software license, see the -// accompanying file LICENSE in the main directory of the -// repository or http://www.opensource.org/licenses/mit-license.php -// for more details. -// -// Redistribution and use in source and binary forms with or without -// modifications are permitted. - -using System; - -namespace Neo.Plugins -{ - [Flags] - internal enum PersistActions : byte - { - StorageChanges = 0b00000001 - } -} diff --git a/src/Plugins/StatesDumper/Settings.cs b/src/Plugins/StatesDumper/Settings.cs deleted file mode 100644 index 8fd3b9e163..0000000000 --- a/src/Plugins/StatesDumper/Settings.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2015-2024 The Neo Project. -// -// Settings.cs file belongs to the neo project and is free -// software distributed under the MIT software license, see the -// accompanying file LICENSE in the main directory of the -// repository or http://www.opensource.org/licenses/mit-license.php -// for more details. -// -// Redistribution and use in source and binary forms with or without -// modifications are permitted. - -using Microsoft.Extensions.Configuration; -using Neo.SmartContract.Native; -using System.Collections.Generic; -using System.Linq; - -namespace Neo.Plugins -{ - internal class Settings - { - /// - /// Amount of storages states (heights) to be dump in a given json file - /// - public uint BlockCacheSize { get; } - /// - /// Height to begin storage dump - /// - public uint HeightToBegin { get; } - /// - /// Height to begin real-time syncing and dumping on, consequently, dumping every block into a single files - /// - public int HeightToStartRealTimeSyncing { get; } - /// - /// Persisting actions - /// - public PersistActions PersistAction { get; } - public IReadOnlyList Exclude { get; } - - public static Settings Default { get; private set; } - - private Settings(IConfigurationSection section) - { - /// Geting settings for storage changes state dumper - BlockCacheSize = section.GetValue("BlockCacheSize", 1000u); - HeightToBegin = section.GetValue("HeightToBegin", 0u); - HeightToStartRealTimeSyncing = section.GetValue("HeightToStartRealTimeSyncing", -1); - PersistAction = section.GetValue("PersistAction", PersistActions.StorageChanges); - Exclude = section.GetSection("Exclude").Exists() - ? section.GetSection("Exclude").GetChildren().Select(p => int.Parse(p.Value)).ToArray() - : new[] { NativeContract.Ledger.Id }; - } - - public static void Load(IConfigurationSection section) - { - Default = new Settings(section); - } - } -} diff --git a/src/Plugins/StatesDumper/StatesDumper.cs b/src/Plugins/StatesDumper/StatesDumper.cs deleted file mode 100644 index da1bbd3f69..0000000000 --- a/src/Plugins/StatesDumper/StatesDumper.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (C) 2015-2024 The Neo Project. -// -// StatesDumper.cs file belongs to the neo project and is free -// software distributed under the MIT software license, see the -// accompanying file LICENSE in the main directory of the -// repository or http://www.opensource.org/licenses/mit-license.php -// for more details. -// -// Redistribution and use in source and binary forms with or without -// modifications are permitted. - -using Neo.ConsoleService; -using Neo.IO; -using Neo.Json; -using Neo.Ledger; -using Neo.Network.P2P.Payloads; -using Neo.Persistence; -using Neo.SmartContract.Native; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Neo.Plugins -{ - public class StatesDumper : Plugin - { - private readonly Dictionary bs_cache = new Dictionary(); - private readonly Dictionary systems = new Dictionary(); - - public override string Description => "Exports Neo-CLI status data"; - - public override string ConfigFile => System.IO.Path.Combine(RootPath, "StatesDumper.json"); - - public StatesDumper() - { - Blockchain.Committing += OnCommitting; - Blockchain.Committed += OnCommitted; - } - - public override void Dispose() - { - Blockchain.Committing -= OnCommitting; - Blockchain.Committed -= OnCommitted; - } - - protected override void Configure() - { - Settings.Load(GetConfiguration()); - } - - protected override void OnSystemLoaded(NeoSystem system) - { - systems.Add(system.Settings.Network, system); - } - - /// - /// Process "dump storage" command - /// - [ConsoleCommand("dump storage", Category = "Storage", Description = "You can specify the contract script hash or use null to get the corresponding information from the storage")] - private void OnDumpStorage(uint network, UInt160 contractHash = null) - { - if (!systems.ContainsKey(network)) throw new InvalidOperationException("invalid network"); - string path = $"dump_{network:x8}.json"; - byte[] prefix = null; - if (contractHash is not null) - { - var contract = NativeContract.ContractManagement.GetContract(systems[network].StoreView, contractHash); - if (contract is null) throw new InvalidOperationException("contract not found"); - prefix = BitConverter.GetBytes(contract.Id); - } - var states = systems[network].StoreView.Find(prefix); - JArray array = new JArray(states.Where(p => !Settings.Default.Exclude.Contains(p.Key.Id)).Select(p => new JObject - { - ["key"] = Convert.ToBase64String(p.Key.ToArray()), - ["value"] = Convert.ToBase64String(p.Value.ToArray()) - })); - File.WriteAllText(path, array.ToString()); - ConsoleHelper.Info("States", - $"({array.Count})", - " have been dumped into file ", - $"{path}"); - } - - private void OnCommitting(NeoSystem system, Block block, DataCache snapshot, IReadOnlyList applicationExecutedList) - { - if (Settings.Default.PersistAction.HasFlag(PersistActions.StorageChanges)) - OnPersistStorage(system.Settings.Network, snapshot); - } - - private void OnPersistStorage(uint network, DataCache snapshot) - { - uint blockIndex = NativeContract.Ledger.CurrentIndex(snapshot); - if (blockIndex >= Settings.Default.HeightToBegin) - { - JArray array = new JArray(); - - foreach (var trackable in snapshot.GetChangeSet()) - { - if (Settings.Default.Exclude.Contains(trackable.Key.Id)) - continue; - JObject state = new JObject(); - switch (trackable.State) - { - case TrackState.Added: - state["state"] = "Added"; - state["key"] = Convert.ToBase64String(trackable.Key.ToArray()); - state["value"] = Convert.ToBase64String(trackable.Item.ToArray()); - // Here we have a new trackable.Key and trackable.Item - break; - case TrackState.Changed: - state["state"] = "Changed"; - state["key"] = Convert.ToBase64String(trackable.Key.ToArray()); - state["value"] = Convert.ToBase64String(trackable.Item.ToArray()); - break; - case TrackState.Deleted: - state["state"] = "Deleted"; - state["key"] = Convert.ToBase64String(trackable.Key.ToArray()); - break; - } - array.Add(state); - } - - JObject bs_item = new JObject(); - bs_item["block"] = blockIndex; - bs_item["size"] = array.Count; - bs_item["storage"] = array; - if (!bs_cache.TryGetValue(network, out JArray cache)) - { - cache = new JArray(); - } - cache.Add(bs_item); - bs_cache[network] = cache; - } - } - - private void OnCommitted(NeoSystem system, Block block) - { - if (Settings.Default.PersistAction.HasFlag(PersistActions.StorageChanges)) - OnCommitStorage(system.Settings.Network, system.StoreView); - } - - void OnCommitStorage(uint network, DataCache snapshot) - { - if (!bs_cache.TryGetValue(network, out JArray cache)) return; - if (cache.Count == 0) return; - uint blockIndex = NativeContract.Ledger.CurrentIndex(snapshot); - if ((blockIndex % Settings.Default.BlockCacheSize == 0) || (Settings.Default.HeightToStartRealTimeSyncing != -1 && blockIndex >= Settings.Default.HeightToStartRealTimeSyncing)) - { - string path = HandlePaths(network, blockIndex); - path = $"{path}/dump-block-{blockIndex}.json"; - File.WriteAllText(path, cache.ToString()); - cache.Clear(); - } - } - - private static string HandlePaths(uint network, uint blockIndex) - { - //Default Parameter - uint storagePerFolder = 100000; - uint folder = (((blockIndex - 1) / storagePerFolder) + 1) * storagePerFolder; - if (blockIndex == 0) - folder = 0; - string dirPathWithBlock = $"./Storage_{network:x8}/BlockStorage_{folder}"; - Directory.CreateDirectory(dirPathWithBlock); - return dirPathWithBlock; - } - } -} diff --git a/src/Plugins/StatesDumper/StatesDumper.csproj b/src/Plugins/StatesDumper/StatesDumper.csproj deleted file mode 100644 index 4ebf25f2c1..0000000000 --- a/src/Plugins/StatesDumper/StatesDumper.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net8.0 - Neo.Plugins.StatesDumper - - - - - - - - - PreserveNewest - - - - diff --git a/src/Plugins/StatesDumper/StatesDumper.json b/src/Plugins/StatesDumper/StatesDumper.json deleted file mode 100644 index c3b73767dd..0000000000 --- a/src/Plugins/StatesDumper/StatesDumper.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "PluginConfiguration": { - "PersistAction": "StorageChanges", - "BlockCacheSize": 1000, - "HeightToBegin": 0, - "HeightToStartRealTimeSyncing": -1, - "Exclude": [ -4 ] - } -} diff --git a/src/Plugins/StorageDumper/Settings.cs b/src/Plugins/StorageDumper/Settings.cs index 84fe2b2231..c2761ce6b9 100644 --- a/src/Plugins/StorageDumper/Settings.cs +++ b/src/Plugins/StorageDumper/Settings.cs @@ -12,7 +12,7 @@ using Microsoft.Extensions.Configuration; using Neo.SmartContract.Native; -namespace Neo.Plugins +namespace Neo.Plugins.StorageDumper { internal class Settings { @@ -24,18 +24,22 @@ internal class Settings /// Height to begin storage dump /// public uint HeightToBegin { get; } - + /// + /// Default number of items per folder + /// + public uint StoragePerFolder { get; } public IReadOnlyList Exclude { get; } public static Settings? Default { get; private set; } private Settings(IConfigurationSection section) { - /// Geting settings for storage changes state dumper + // Geting settings for storage changes state dumper BlockCacheSize = section.GetValue("BlockCacheSize", 1000u); HeightToBegin = section.GetValue("HeightToBegin", 0u); + StoragePerFolder = section.GetValue("StoragePerFolder", 100000u); Exclude = section.GetSection("Exclude").Exists() - ? section.GetSection("Exclude").GetChildren().Select(p => int.Parse(p.Value)).ToArray() + ? section.GetSection("Exclude").GetChildren().Select(p => int.Parse(p.Value!)).ToArray() : new[] { NativeContract.Ledger.Id }; } diff --git a/src/Plugins/StorageDumper/StorageDumper.cs b/src/Plugins/StorageDumper/StorageDumper.cs index 696f5014ac..d8987cdcaa 100644 --- a/src/Plugins/StorageDumper/StorageDumper.cs +++ b/src/Plugins/StorageDumper/StorageDumper.cs @@ -17,15 +17,18 @@ using Neo.Persistence; using Neo.SmartContract.Native; -namespace Neo.Plugins +namespace Neo.Plugins.StorageDumper { public class StorageDumper : Plugin { private readonly Dictionary systems = new Dictionary(); - private StreamWriter _writer; - private JObject _currentBlock; - private string _lastCreateDirectory; + private StreamWriter? _writer; + /// + /// _currentBlock stores the last cached item + /// + private JObject? _currentBlock; + private string? _lastCreateDirectory; public override string Description => "Exports Neo-CLI status data"; @@ -70,7 +73,7 @@ private void OnDumpStorage(uint network, UInt160? contractHash = null) prefix = BitConverter.GetBytes(contract.Id); } var states = systems[network].StoreView.Find(prefix); - JArray array = new JArray(states.Where(p => !Settings.Default.Exclude.Contains(p.Key.Id)).Select(p => new JObject + JArray array = new JArray(states.Where(p => !Settings.Default!.Exclude.Contains(p.Key.Id)).Select(p => new JObject { ["key"] = Convert.ToBase64String(p.Key.ToArray()), ["value"] = Convert.ToBase64String(p.Value.ToArray()) @@ -91,9 +94,9 @@ private void OnCommitting(NeoSystem system, Block block, DataCache snapshot, IRe private void OnPersistStorage(uint network, DataCache snapshot) { uint blockIndex = NativeContract.Ledger.CurrentIndex(snapshot); - if (blockIndex >= Settings.Default.HeightToBegin) + if (blockIndex >= Settings.Default!.HeightToBegin) { - JArray array = new JArray(); + JArray stateChangeArray = new JArray(); foreach (var trackable in snapshot.GetChangeSet()) { @@ -106,7 +109,6 @@ private void OnPersistStorage(uint network, DataCache snapshot) state["state"] = "Added"; state["key"] = Convert.ToBase64String(trackable.Key.ToArray()); state["value"] = Convert.ToBase64String(trackable.Item.ToArray()); - // Here we have a new trackable.Key and trackable.Item break; case TrackState.Changed: state["state"] = "Changed"; @@ -118,13 +120,13 @@ private void OnPersistStorage(uint network, DataCache snapshot) state["key"] = Convert.ToBase64String(trackable.Key.ToArray()); break; } - array.Add(state); + stateChangeArray.Add(state); } JObject bs_item = new JObject(); bs_item["block"] = blockIndex; - bs_item["size"] = array.Count; - bs_item["storage"] = array; + bs_item["size"] = stateChangeArray.Count; + bs_item["storage"] = stateChangeArray; _currentBlock = bs_item; } } @@ -137,7 +139,7 @@ private void OnCommitted(NeoSystem system, Block block) void OnCommitStorage(uint network, DataCache snapshot) { - if (_currentBlock != null) + if (_currentBlock != null && _writer != null) { _writer.WriteLine(_currentBlock.ToString()); _writer.Flush(); @@ -148,10 +150,10 @@ private void InitFileWriter(uint network, DataCache snapshot) { uint blockIndex = NativeContract.Ledger.CurrentIndex(snapshot); if (_writer == null - || blockIndex % Settings.Default.BlockCacheSize == 0) + || blockIndex % Settings.Default!.BlockCacheSize == 0) { string path = GetOrCreateDirectory(network, blockIndex); - var filepart = (blockIndex / Settings.Default.BlockCacheSize) * Settings.Default.BlockCacheSize; + var filepart = (blockIndex / Settings.Default!.BlockCacheSize) * Settings.Default.BlockCacheSize; path = $"{path}/dump-block-{filepart}.dump"; if (_writer != null) { @@ -174,9 +176,7 @@ private string GetOrCreateDirectory(uint network, uint blockIndex) private string GetDirectoryPath(uint network, uint blockIndex) { - //Default Parameter - uint storagePerFolder = 100000; - uint folder = (blockIndex / storagePerFolder) * storagePerFolder; + uint folder = (blockIndex / Settings.Default!.StoragePerFolder) * Settings.Default.StoragePerFolder; return $"./StorageDumper_{network}/BlockStorage_{folder}"; } diff --git a/src/Plugins/StorageDumper/StorageDumper.csproj b/src/Plugins/StorageDumper/StorageDumper.csproj index 49d5362538..7805140f3e 100644 --- a/src/Plugins/StorageDumper/StorageDumper.csproj +++ b/src/Plugins/StorageDumper/StorageDumper.csproj @@ -5,6 +5,7 @@ Neo.Plugins.StorageDumper enable enable + $(SolutionDir)/bin/$(PackageId) diff --git a/src/Plugins/StorageDumper/StorageDumper.json b/src/Plugins/StorageDumper/StorageDumper.json index 3f5c0537f0..b327c37e0c 100644 --- a/src/Plugins/StorageDumper/StorageDumper.json +++ b/src/Plugins/StorageDumper/StorageDumper.json @@ -2,6 +2,7 @@ "PluginConfiguration": { "BlockCacheSize": 1000, "HeightToBegin": 0, + "StoragePerFolder": 100000, "Exclude": [ -4 ] } } diff --git a/src/Plugins/TokensTracker/TokensTracker.cs b/src/Plugins/TokensTracker/TokensTracker.cs index 0d8863a767..eacd0de6e4 100644 --- a/src/Plugins/TokensTracker/TokensTracker.cs +++ b/src/Plugins/TokensTracker/TokensTracker.cs @@ -10,12 +10,11 @@ // modifications are permitted. using Microsoft.Extensions.Configuration; -using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.RpcServer; using Neo.Plugins.Trackers; -using System; using System.Collections.Generic; using System.Linq; using static System.IO.Path; diff --git a/src/Plugins/TokensTracker/TokensTracker.csproj b/src/Plugins/TokensTracker/TokensTracker.csproj index 7c3df5c0c6..bdacd3839c 100644 --- a/src/Plugins/TokensTracker/TokensTracker.csproj +++ b/src/Plugins/TokensTracker/TokensTracker.csproj @@ -1,8 +1,9 @@ - + net8.0 Neo.Plugins.TokensTracker + $(SolutionDir)/bin/$(PackageId) @@ -15,4 +16,4 @@ - \ No newline at end of file + diff --git a/src/Plugins/TokensTracker/Trackers/NEP-11/Nep11Tracker.cs b/src/Plugins/TokensTracker/Trackers/NEP-11/Nep11Tracker.cs index 35a579eb77..12d3c208bc 100644 --- a/src/Plugins/TokensTracker/Trackers/NEP-11/Nep11Tracker.cs +++ b/src/Plugins/TokensTracker/Trackers/NEP-11/Nep11Tracker.cs @@ -13,6 +13,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.RpcServer; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; diff --git a/src/Plugins/TokensTracker/Trackers/NEP-17/Nep17Tracker.cs b/src/Plugins/TokensTracker/Trackers/NEP-17/Nep17Tracker.cs index 8ea2efa6a6..d4698cba1e 100644 --- a/src/Plugins/TokensTracker/Trackers/NEP-17/Nep17Tracker.cs +++ b/src/Plugins/TokensTracker/Trackers/NEP-17/Nep17Tracker.cs @@ -13,6 +13,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.Plugins.RpcServer; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 7ba3905160..a2fc251365 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -7,6 +7,9 @@ false true 0 + true + TestResults/ + lcov diff --git a/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs b/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs index 88c08575fa..d689578e22 100644 --- a/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs +++ b/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs @@ -12,7 +12,7 @@ using Neo.Persistence; using System; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService.Tests { public static class TestBlockchain { diff --git a/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs b/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs index 5700b83769..7f1c3a58d5 100644 --- a/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs +++ b/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs @@ -13,7 +13,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; -namespace Neo.Plugins +namespace Neo.Plugins.OracleService.Tests { public static class TestUtils { diff --git a/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs b/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs index 08f96c95d7..9622ceb9e2 100644 --- a/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs +++ b/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs @@ -16,7 +16,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; -namespace Neo.Plugins.Tests +namespace Neo.Plugins.OracleService.Tests { [TestClass] public class UT_OracleService : TestKit diff --git a/tests/Neo.Plugins.RpcServer.Tests/MockNeoSystem.cs b/tests/Neo.Plugins.RpcServer.Tests/MockNeoSystem.cs new file mode 100644 index 0000000000..0f45a63d98 --- /dev/null +++ b/tests/Neo.Plugins.RpcServer.Tests/MockNeoSystem.cs @@ -0,0 +1,34 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// MockNeoSystem.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Ledger; +using Neo.Persistence; + +namespace Neo.Plugins.RpcServer.Tests +{ + public class MockNeoSystem : NeoSystem + { + public SnapshotCache SnapshotCache { get; } + public MemoryPool MemoryPool { get; } + + public MockNeoSystem(SnapshotCache snapshotCache, MemoryPool memoryPool) + : base(TestProtocolSettings.Default, new TestBlockchain.StoreProvider()) + { + SnapshotCache = snapshotCache; + MemoryPool = memoryPool; + } + + public SnapshotCache GetSnapshot() + { + return SnapshotCache; + } + } +} diff --git a/tests/Neo.Plugins.RpcServer.Tests/Neo.Plugins.RpcServer.Tests.csproj b/tests/Neo.Plugins.RpcServer.Tests/Neo.Plugins.RpcServer.Tests.csproj index 2459b1cb5f..5b693c96b8 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/Neo.Plugins.RpcServer.Tests.csproj +++ b/tests/Neo.Plugins.RpcServer.Tests/Neo.Plugins.RpcServer.Tests.csproj @@ -8,11 +8,13 @@ + + diff --git a/tests/Neo.Plugins.RpcServer.Tests/TestBlockchain.cs b/tests/Neo.Plugins.RpcServer.Tests/TestBlockchain.cs new file mode 100644 index 0000000000..f6e35cf695 --- /dev/null +++ b/tests/Neo.Plugins.RpcServer.Tests/TestBlockchain.cs @@ -0,0 +1,49 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestBlockchain.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.Ledger; +using Neo.Persistence; +using System; + +namespace Neo.Plugins.RpcServer.Tests +{ + public static class TestBlockchain + { + public static readonly NeoSystem TheNeoSystem; + public static readonly UInt160[] DefaultExtensibleWitnessWhiteList; + private static readonly MemoryStore Store = new(); + + internal class StoreProvider : IStoreProvider + { + public string Name => "TestProvider"; + + public IStore GetStore(string path) => Store; + } + + static TestBlockchain() + { + Console.WriteLine("initialize NeoSystem"); + TheNeoSystem = new NeoSystem(TestProtocolSettings.Default, new StoreProvider()); + } + + internal static void ResetStore() + { + Store.Reset(); + TheNeoSystem.Blockchain.Ask(new Blockchain.Initialize()).Wait(); + } + + internal static DataCache GetTestSnapshot() + { + return TheNeoSystem.GetSnapshot().CreateSnapshot(); + } + } +} diff --git a/tests/Neo.Plugins.RpcServer.Tests/TestProtocolSettings.cs b/tests/Neo.Plugins.RpcServer.Tests/TestProtocolSettings.cs new file mode 100644 index 0000000000..edf2df39fb --- /dev/null +++ b/tests/Neo.Plugins.RpcServer.Tests/TestProtocolSettings.cs @@ -0,0 +1,65 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestProtocolSettings.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography.ECC; + +namespace Neo.Plugins.RpcServer.Tests +{ + public static class TestProtocolSettings + { + public static readonly ProtocolSettings Default = new() + { + Network = 0x334F454Eu, + AddressVersion = ProtocolSettings.Default.AddressVersion, + StandbyCommittee = new[] + { + //Validators + ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1), + ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", ECCurve.Secp256r1), + ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", ECCurve.Secp256r1), + ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", ECCurve.Secp256r1), + ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", ECCurve.Secp256r1), + ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", ECCurve.Secp256r1), + ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", ECCurve.Secp256r1), + //Other Members + ECPoint.Parse("023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", ECCurve.Secp256r1), + ECPoint.Parse("03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", ECCurve.Secp256r1), + ECPoint.Parse("03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", ECCurve.Secp256r1), + ECPoint.Parse("03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", ECCurve.Secp256r1), + ECPoint.Parse("02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", ECCurve.Secp256r1), + ECPoint.Parse("03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", ECCurve.Secp256r1), + ECPoint.Parse("0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", ECCurve.Secp256r1), + ECPoint.Parse("020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", ECCurve.Secp256r1), + ECPoint.Parse("0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", ECCurve.Secp256r1), + ECPoint.Parse("03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", ECCurve.Secp256r1), + ECPoint.Parse("02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", ECCurve.Secp256r1), + ECPoint.Parse("0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", ECCurve.Secp256r1), + ECPoint.Parse("03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", ECCurve.Secp256r1), + ECPoint.Parse("02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a", ECCurve.Secp256r1) + }, + ValidatorsCount = 7, + SeedList = new[] + { + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + }, + MillisecondsPerBlock = ProtocolSettings.Default.MillisecondsPerBlock, + MaxTransactionsPerBlock = ProtocolSettings.Default.MaxTransactionsPerBlock, + MemoryPoolMaxTransactions = ProtocolSettings.Default.MemoryPoolMaxTransactions, + MaxTraceableBlocks = ProtocolSettings.Default.MaxTraceableBlocks, + InitialGasDistribution = ProtocolSettings.Default.InitialGasDistribution, + Hardforks = ProtocolSettings.Default.Hardforks + }; + } +} diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_Result.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_Result.cs new file mode 100644 index 0000000000..aa6a8fe308 --- /dev/null +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_Result.cs @@ -0,0 +1,26 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// UT_Result.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.SmartContract; + +namespace Neo.Plugins.RpcServer.Tests; + +[TestClass] +public class UT_Result +{ + [TestMethod] + public void TestNotNull_Or() + { + ContractState? contracts = null; + Assert.ThrowsException(() => contracts.NotNull_Or(RpcError.UnknownContract).ToJson()); + } +} diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.cs index 803980eb8f..7bca550b83 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.cs @@ -9,12 +9,53 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Microsoft.AspNetCore.Http; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Ledger; +using Neo.Persistence; +using System; +using System.Text; namespace Neo.Plugins.RpcServer.Tests { [TestClass] - public class UT_RpcServer + public partial class UT_RpcServer { + private Mock _systemMock; + private SnapshotCache _snapshotCache; + private MemoryPool _memoryPool; + private RpcServerSettings _settings; + private RpcServer _rpcServer; + + [TestInitialize] + public void TestSetup() + { + // Mock IReadOnlyStore + var mockStore = new Mock(); + + // Initialize SnapshotCache with the mock IReadOnlyStore + _snapshotCache = new SnapshotCache(mockStore.Object); + + // Initialize NeoSystem + var neoSystem = new NeoSystem(TestProtocolSettings.Default, new TestBlockchain.StoreProvider()); + + // Initialize MemoryPool with the NeoSystem + _memoryPool = new MemoryPool(neoSystem); + + // Set up the mock system with the correct constructor arguments + _systemMock = new Mock(_snapshotCache, _memoryPool); + + _rpcServer = new RpcServer(_systemMock.Object, RpcServerSettings.Default); + } + + [TestMethod] + public void TestCheckAuth_ValidCredentials_ReturnsTrue() + { + var context = new DefaultHttpContext(); + context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("testuser:testpass")); + var result = _rpcServer.CheckAuth(context); + Assert.IsTrue(result); + } } } diff --git a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs index 9e72fc7ec3..9a282759a9 100644 --- a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -21,13 +21,23 @@ namespace Neo.UnitTests.Extensions { public static class NativeContractExtensions { - public static ContractState DeployContract(this DataCache snapshot, UInt160 sender, byte[] nefFile, byte[] manifest, long gas = 200_00000000) + /// + /// Deploy a contract to the blockchain. + /// + /// The snapshot used for deploying the contract. + /// The address of the contract deployer. + /// The file of the contract to be deployed. + /// The manifest of the contract to be deployed. + /// The gas fee to spend for deploying the contract in the unit of datoshi, 1 datoshi = 1e-8 GAS. + /// + /// + public static ContractState DeployContract(this DataCache snapshot, UInt160 sender, byte[] nefFile, byte[] manifest, long datoshi = 200_00000000) { var script = new ScriptBuilder(); script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nefFile, manifest, null); var engine = ApplicationEngine.Create(TriggerType.Application, - sender != null ? new Transaction() { Signers = new Signer[] { new Signer() { Account = sender } }, Attributes = System.Array.Empty() } : null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings, gas: gas); + sender != null ? new Transaction() { Signers = new Signer[] { new Signer() { Account = sender } }, Attributes = System.Array.Empty() } : null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings, gas: datoshi); engine.LoadScript(script.ToArray()); if (engine.Execute() != VMState.HALT) diff --git a/tests/Neo.UnitTests/Ledger/UT_PoolItem.cs b/tests/Neo.UnitTests/Ledger/UT_PoolItem.cs index 683291eda9..2b8e54b919 100644 --- a/tests/Neo.UnitTests/Ledger/UT_PoolItem.cs +++ b/tests/Neo.UnitTests/Ledger/UT_PoolItem.cs @@ -47,11 +47,11 @@ public void TestCleanup() public void PoolItem_CompareTo_Fee() { int size1 = 51; - int netFeeSatoshi1 = 1; - var tx1 = GenerateTx(netFeeSatoshi1, size1); + int netFeeDatoshi1 = 1; + var tx1 = GenerateTx(netFeeDatoshi1, size1); int size2 = 51; - int netFeeSatoshi2 = 2; - var tx2 = GenerateTx(netFeeSatoshi2, size2); + int netFeeDatoshi2 = 2; + var tx2 = GenerateTx(netFeeDatoshi2, size2); PoolItem pitem1 = new PoolItem(tx1); PoolItem pitem2 = new PoolItem(tx2); @@ -67,10 +67,10 @@ public void PoolItem_CompareTo_Fee() public void PoolItem_CompareTo_Hash() { int sizeFixed = 51; - int netFeeSatoshiFixed = 1; + int netFeeDatoshiFixed = 1; - var tx1 = GenerateTxWithFirstByteOfHashGreaterThanOrEqualTo(0x80, netFeeSatoshiFixed, sizeFixed); - var tx2 = GenerateTxWithFirstByteOfHashLessThanOrEqualTo(0x79, netFeeSatoshiFixed, sizeFixed); + var tx1 = GenerateTxWithFirstByteOfHashGreaterThanOrEqualTo(0x80, netFeeDatoshiFixed, sizeFixed); + var tx2 = GenerateTxWithFirstByteOfHashLessThanOrEqualTo(0x79, netFeeDatoshiFixed, sizeFixed); tx1.Attributes = new TransactionAttribute[] { new HighPriorityAttribute() }; @@ -83,8 +83,8 @@ public void PoolItem_CompareTo_Hash() // Bulk test for (int testRuns = 0; testRuns < 30; testRuns++) { - tx1 = GenerateTxWithFirstByteOfHashGreaterThanOrEqualTo(0x80, netFeeSatoshiFixed, sizeFixed); - tx2 = GenerateTxWithFirstByteOfHashLessThanOrEqualTo(0x79, netFeeSatoshiFixed, sizeFixed); + tx1 = GenerateTxWithFirstByteOfHashGreaterThanOrEqualTo(0x80, netFeeDatoshiFixed, sizeFixed); + tx2 = GenerateTxWithFirstByteOfHashLessThanOrEqualTo(0x79, netFeeDatoshiFixed, sizeFixed); pitem1 = new PoolItem(tx1); pitem2 = new PoolItem(tx2); @@ -103,8 +103,8 @@ public void PoolItem_CompareTo_Hash() public void PoolItem_CompareTo_Equals() { int sizeFixed = 500; - int netFeeSatoshiFixed = 10; - var tx = GenerateTx(netFeeSatoshiFixed, sizeFixed, new byte[] { 0x13, 0x37 }); + int netFeeDatoshiFixed = 10; + var tx = GenerateTx(netFeeDatoshiFixed, sizeFixed, new byte[] { 0x13, 0x37 }); PoolItem pitem1 = new PoolItem(tx); PoolItem pitem2 = new PoolItem(tx); diff --git a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index 43755374d3..56d9a66bec 100644 --- a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -187,7 +187,7 @@ public void FeeIsMultiSigContract() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); @@ -263,7 +263,7 @@ public void FeeIsSignatureContractDetailed() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } // ------------------ @@ -368,7 +368,7 @@ public void FeeIsSignatureContract_TestScope_Global() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); @@ -448,7 +448,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); @@ -531,7 +531,7 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); @@ -661,7 +661,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); @@ -818,7 +818,7 @@ public void Transaction_Serialize_Deserialize_Simple() "00" + // version "04030201" + // nonce "00e1f50500000000" + // system fee (1 GAS) - "0100000000000000" + // network fee (1 satoshi) + "0100000000000000" + // network fee (1 datoshi) "04030201" + // timelimit "01000000000000000000000000000000000000000000" + // empty signer "00" + // no attributes @@ -1050,7 +1050,7 @@ public void FeeIsSignatureContract_TestScope_FeeOnly_Default() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - verificationGas += engine.GasConsumed; + verificationGas += engine.FeeConsumed; } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); diff --git a/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs b/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs index 88d48ba548..b0f61791f6 100644 --- a/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs +++ b/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs @@ -11,8 +11,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Persistence; +using Neo.SmartContract; using System; using System.Linq; +using System.Text; namespace Neo.UnitTests.Persistence { @@ -30,27 +32,42 @@ public void StoreTest() { using var store = new MemoryStore(); - store.Delete(new byte[] { 1 }); - Assert.AreEqual(null, store.TryGet(new byte[] { 1 })); - store.Put(new byte[] { 1 }, new byte[] { 1, 2, 3 }); - CollectionAssert.AreEqual(new byte[] { 1, 2, 3 }, store.TryGet(new byte[] { 1 })); + store.Delete([1]); + Assert.AreEqual(null, store.TryGet([1])); + store.Put([1], [1, 2, 3]); + CollectionAssert.AreEqual(new byte[] { 1, 2, 3 }, store.TryGet([1])); - store.Put(new byte[] { 2 }, new byte[] { 4, 5, 6 }); - CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(Array.Empty(), SeekDirection.Forward).Select(u => u.Key).First()); - CollectionAssert.AreEqual(new byte[] { 2 }, store.Seek(new byte[] { 2 }, SeekDirection.Backward).Select(u => u.Key).First()); - CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(new byte[] { 1 }, SeekDirection.Backward).Select(u => u.Key).First()); + store.Put([2], [4, 5, 6]); + CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek(Array.Empty()).Select(u => u.Key).First()); + CollectionAssert.AreEqual(new byte[] { 2 }, store.Seek([2], SeekDirection.Backward).Select(u => u.Key).First()); + CollectionAssert.AreEqual(new byte[] { 1 }, store.Seek([1], SeekDirection.Backward).Select(u => u.Key).First()); - store.Delete(new byte[] { 1 }); - store.Delete(new byte[] { 2 }); + store.Delete([1]); + store.Delete([2]); - store.Put(new byte[] { 0x00, 0x00, 0x00 }, new byte[] { 0x00 }); - store.Put(new byte[] { 0x00, 0x00, 0x01 }, new byte[] { 0x01 }); - store.Put(new byte[] { 0x00, 0x00, 0x02 }, new byte[] { 0x02 }); - store.Put(new byte[] { 0x00, 0x00, 0x03 }, new byte[] { 0x03 }); - store.Put(new byte[] { 0x00, 0x00, 0x04 }, new byte[] { 0x04 }); + store.Put([0x00, 0x00, 0x00], [0x00]); + store.Put([0x00, 0x00, 0x01], [0x01]); + store.Put([0x00, 0x00, 0x02], [0x02]); + store.Put([0x00, 0x00, 0x03], [0x03]); + store.Put([0x00, 0x00, 0x04], [0x04]); var entries = store.Seek(Array.Empty(), SeekDirection.Backward).ToArray(); - Assert.AreEqual(entries.Count(), 0); + Assert.AreEqual(entries.Length, 0); } + + [TestMethod] + public void NeoSystemStoreViewTest() + { + var neoSystem = new NeoSystem(TestProtocolSettings.Default, new MemoryStoreProvider()); + Assert.IsNotNull(neoSystem.StoreView); + var store = neoSystem.StoreView; + var key = new StorageKey(Encoding.UTF8.GetBytes("testKey")); + var value = new StorageItem(Encoding.UTF8.GetBytes("testValue")); + store.Add(key, value); + store.Commit(); + var result = store.TryGet(key); + Assert.AreEqual("testValue", Encoding.UTF8.GetString(result.Value.ToArray())); + } + } } diff --git a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs index 7639377fe1..0969e12776 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs @@ -12,6 +12,9 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; +using Neo.SmartContract.Manifest; +using Neo.UnitTests.Extensions; +using Neo.VM; using System; using System.Collections.Immutable; using System.Linq; @@ -103,5 +106,103 @@ public void TestCheckingHardfork() (setting[sortedHardforks[i]] > setting[sortedHardforks[i + 1]]).Should().Be(false); } } + + [TestMethod] + public void TestSystem_Contract_Call_Permissions() + { + UInt160 scriptHash; + var snapshot = TestBlockchain.GetTestSnapshot(); + + // Setup: put a simple contract to the storage. + using (var script = new ScriptBuilder()) + { + // Push True on stack and return. + script.EmitPush(true); + script.Emit(OpCode.RET); + + // Mock contract and put it to the Managemant's storage. + scriptHash = script.ToArray().ToScriptHash(); + + snapshot.DeleteContract(scriptHash); + var contract = TestUtils.GetContract(script.ToArray(), TestUtils.CreateManifest("test", ContractParameterType.Any)); + contract.Manifest.Abi.Methods = new[] + { + new ContractMethodDescriptor + { + Name = "disallowed", + Parameters = new ContractParameterDefinition[]{} + }, + new ContractMethodDescriptor + { + Name = "test", + Parameters = new ContractParameterDefinition[]{} + } + }; + snapshot.AddContract(scriptHash, contract); + } + + // Disallowed method call. + using (var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default)) + using (var script = new ScriptBuilder()) + { + // Build call script calling disallowed method. + script.EmitDynamicCall(scriptHash, "disallowed"); + + // Mock executing state to be a contract-based. + engine.LoadScript(script.ToArray()); + engine.CurrentContext.GetState().Contract = new() + { + Manifest = new() + { + Abi = new() { }, + Permissions = new ContractPermission[] + { + new ContractPermission + { + Contract = ContractPermissionDescriptor.Create(scriptHash), + Methods = WildcardContainer.Create(new string[]{"test"}) // allowed to call only "test" method of the target contract. + } + } + } + }; + var currentScriptHash = engine.EntryScriptHash; + + Assert.AreEqual(VMState.FAULT, engine.Execute()); + Assert.IsTrue(engine.FaultException.ToString().Contains($"Cannot Call Method disallowed Of Contract {scriptHash.ToString()}")); + } + + // Allowed method call. + using (var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default)) + using (var script = new ScriptBuilder()) + { + // Build call script. + script.EmitDynamicCall(scriptHash, "test"); + + // Mock executing state to be a contract-based. + engine.LoadScript(script.ToArray()); + engine.CurrentContext.GetState().Contract = new() + { + Manifest = new() + { + Abi = new() { }, + Permissions = new ContractPermission[] + { + new ContractPermission + { + Contract = ContractPermissionDescriptor.Create(scriptHash), + Methods = WildcardContainer.Create(new string[]{"test"}) // allowed to call only "test" method of the target contract. + } + } + } + }; + var currentScriptHash = engine.EntryScriptHash; + + Assert.AreEqual(VMState.HALT, engine.Execute()); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Boolean)); + var res = (VM.Types.Boolean)engine.ResultStack.Pop(); + Assert.IsTrue(res.GetBoolean()); + } + } } } diff --git a/tests/Neo.UnitTests/SmartContract/UT_Contract.cs b/tests/Neo.UnitTests/SmartContract/UT_Contract.cs index a263779282..07ae320a0f 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_Contract.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_Contract.cs @@ -170,7 +170,7 @@ public void TestSignatureRedeemScriptFee() { engine.LoadScript(invocation.Concat(verification).ToArray(), configureState: p => p.CallFlags = CallFlags.None); engine.Execute(); - engine.GasConsumed.Should().Be(fee); + engine.FeeConsumed.Should().Be(fee); } } @@ -198,7 +198,7 @@ public void TestCreateMultiSigRedeemScriptFee() { engine.LoadScript(invocation.Concat(verification).ToArray(), configureState: p => p.CallFlags = CallFlags.None); engine.Execute(); - engine.GasConsumed.Should().Be(fee); + engine.FeeConsumed.Should().Be(fee); } } } diff --git a/tests/Neo.UnitTests/SmartContract/UT_Helper.cs b/tests/Neo.UnitTests/SmartContract/UT_Helper.cs index ffffc70728..e629a5908f 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_Helper.cs @@ -133,7 +133,7 @@ public void TestSignatureContractCost() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - Assert.AreEqual(Neo.SmartContract.Helper.SignatureContractCost() * PolicyContract.DefaultExecFeeFactor, engine.GasConsumed); + Assert.AreEqual(Neo.SmartContract.Helper.SignatureContractCost() * PolicyContract.DefaultExecFeeFactor, engine.FeeConsumed); } [TestMethod] @@ -153,7 +153,7 @@ public void TestMultiSignatureContractCost() Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); - Assert.AreEqual(Neo.SmartContract.Helper.MultiSignatureContractCost(1, 1) * PolicyContract.DefaultExecFeeFactor, engine.GasConsumed); + Assert.AreEqual(Neo.SmartContract.Helper.MultiSignatureContractCost(1, 1) * PolicyContract.DefaultExecFeeFactor, engine.FeeConsumed); } } } diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs index a55db382df..581bf42751 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -74,9 +74,9 @@ public void ApplicationEngineRegularPut() debugger.StepInto(); debugger.StepInto(); debugger.StepInto(); - var setupPrice = ae.GasConsumed; + var setupPrice = ae.FeeConsumed; debugger.Execute(); - (ae.GasConsumed - setupPrice).Should().Be(ae.StoragePrice * value.Length + (1 << 15) * 30); + (ae.FeeConsumed - setupPrice).Should().Be(ae.StoragePrice * value.Length + (1 << 15) * 30); } /// @@ -105,9 +105,9 @@ public void ApplicationEngineReusedStorage_FullReuse() debugger.StepInto(); debugger.StepInto(); debugger.StepInto(); - var setupPrice = applicationEngine.GasConsumed; + var setupPrice = applicationEngine.FeeConsumed; debugger.Execute(); - (applicationEngine.GasConsumed - setupPrice).Should().Be(1 * applicationEngine.StoragePrice + (1 << 15) * 30); + (applicationEngine.FeeConsumed - setupPrice).Should().Be(1 * applicationEngine.StoragePrice + (1 << 15) * 30); } /// @@ -138,10 +138,10 @@ public void ApplicationEngineReusedStorage_PartialReuse() debugger.StepInto(); debugger.StepInto(); debugger.StepInto(); - var setupPrice = ae.GasConsumed; + var setupPrice = ae.FeeConsumed; debugger.StepInto(); debugger.StepInto(); - (ae.GasConsumed - setupPrice).Should().Be((1 + (oldValue.Length / 4) + value.Length - oldValue.Length) * ae.StoragePrice + (1 << 15) * 30); + (ae.FeeConsumed - setupPrice).Should().Be((1 + (oldValue.Length / 4) + value.Length - oldValue.Length) * ae.StoragePrice + (1 << 15) * 30); } /// @@ -176,9 +176,9 @@ public void ApplicationEngineReusedStorage_PartialReuseTwice() debugger.StepInto(); //push value debugger.StepInto(); //push key debugger.StepInto(); //syscall Storage.GetContext - var setupPrice = ae.GasConsumed; + var setupPrice = ae.FeeConsumed; debugger.StepInto(); //syscall Storage.Put - (ae.GasConsumed - setupPrice).Should().Be((sItem.Value.Length / 4 + 1) * ae.StoragePrice + (1 << 15) * 30); // = PUT basic fee + (ae.FeeConsumed - setupPrice).Should().Be((sItem.Value.Length / 4 + 1) * ae.StoragePrice + (1 << 15) * 30); // = PUT basic fee } private static byte[] CreateMultiplePutScript(byte[] key, byte[] value, int times = 2) diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs index 0e9916b7d5..51f26d22eb 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs @@ -71,6 +71,14 @@ public void Runtime_GetNotifications_Test() } } }; + contract.Manifest.Permissions = new ContractPermission[] + { + new ContractPermission + { + Contract = ContractPermissionDescriptor.Create(scriptHash2), + Methods = WildcardContainer.Create(new string[]{"test"}) + } + }; snapshot.AddContract(scriptHash2, contract); } @@ -133,6 +141,14 @@ public void Runtime_GetNotifications_Test() Parameters = System.Array.Empty() } } + }, + Permissions = new ContractPermission[] + { + new ContractPermission + { + Contract = ContractPermissionDescriptor.Create(scriptHash2), + Methods = WildcardContainer.Create(new string[]{"test"}) + } } } }; @@ -202,6 +218,14 @@ public void Runtime_GetNotifications_Test() Parameters = System.Array.Empty() } } + }, + Permissions = new ContractPermission[] + { + new ContractPermission + { + Contract = ContractPermissionDescriptor.Create(scriptHash2), + Methods = WildcardContainer.Create(new string[]{"test"}) + } } } }; @@ -642,7 +666,7 @@ public void TestContract_Call() var args = new VM.Types.Array { 0, 1 }; var state = TestUtils.GetContract(method, args.Count); - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default); engine.LoadScript(new byte[] { 0x01 }); engine.Snapshot.AddContract(state.Hash, state); diff --git a/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs b/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs index fdaeb9106e..59afbbb760 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs @@ -13,6 +13,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; namespace Neo.UnitTests.SmartContract { @@ -27,5 +29,37 @@ public void TestGetScriptContainer() NotifyEventArgs args = new NotifyEventArgs(container, script_hash, "Test", null); args.ScriptContainer.Should().Be(container); } + + + [TestMethod] + public void TestIssue3300() // https://github.com/neo-project/neo/issues/3300 + { + using var engine = ApplicationEngine.Create(TriggerType.Application, null, null, settings: TestProtocolSettings.Default, gas: 1100_00000000); + using (var script = new ScriptBuilder()) + { + // Build call script calling disallowed method. + script.Emit(OpCode.NOP); + // Mock executing state to be a contract-based. + engine.LoadScript(script.ToArray()); + } + + var ns = new Array(engine.ReferenceCounter); + for (var i = 0; i < 500; i++) + { + ns.Add(""); + }; + + var hash = UInt160.Parse("0x179ab5d297fd34ecd48643894242fc3527f42853"); + engine.SendNotification(hash, "Test", ns); + // This should have being 0, but we have optimized the vm to not clean the reference counter + // unless it is necessary, so the reference counter will be 1000. + // Same reason why its 1504 instead of 504. + Assert.AreEqual(1000, engine.ReferenceCounter.Count); + // This will make a deepcopy for the notification, along with the 500 state items. + engine.GetNotifications(hash); + // With the fix of issue 3300, the reference counter calculates not only + // the notifaction items, but also the subitems of the notification state. + Assert.AreEqual(1504, engine.ReferenceCounter.Count); + } } } diff --git a/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs index 0a98b5fd66..7791b8acef 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -257,7 +257,7 @@ public void System_Runtime_GetInvocationCounter() // Execute - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default); engine.LoadScript(script.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); diff --git a/tests/Neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs b/tests/Neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs index aff3561a75..71914c86f0 100644 --- a/tests/Neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs +++ b/tests/Neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Contract = Neo.SmartContract.Contract; @@ -302,6 +303,11 @@ public void TestImportCert() X509Certificate2 cert = NewCertificate(); Assert.IsNotNull(cert); Assert.AreEqual(true, cert.HasPrivateKey); + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Assert.ThrowsException(() => uut.Import(cert)); + return; + } WalletAccount account = uut.Import(cert); Assert.IsNotNull(account); }