From 0d4ea4f0660f6d6614b55d4b861833be8f9c711f Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 29 Mar 2020 16:30:57 +0200 Subject: [PATCH] Attach during invoke --- Neo.ConsoleService/ConsoleServiceBase.cs | 2 +- neo-cli/CLI/MainService.Contracts.cs | 84 +++++++++++++++++++++++- neo-cli/CLI/MainService.cs | 1 + 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/Neo.ConsoleService/ConsoleServiceBase.cs b/Neo.ConsoleService/ConsoleServiceBase.cs index 26d157ed0..4374dd632 100644 --- a/Neo.ConsoleService/ConsoleServiceBase.cs +++ b/Neo.ConsoleService/ConsoleServiceBase.cs @@ -416,7 +416,7 @@ protected ConsoleServiceBase() } else { - return CommandToken.ReadString(args, false).Split(',', ' '); + return CommandToken.ReadString(args, false).Split(',', ' ', StringSplitOptions.RemoveEmptyEntries); } }); diff --git a/neo-cli/CLI/MainService.Contracts.cs b/neo-cli/CLI/MainService.Contracts.cs index f3f4f3d56..711f446a1 100644 --- a/neo-cli/CLI/MainService.Contracts.cs +++ b/neo-cli/CLI/MainService.Contracts.cs @@ -6,14 +6,47 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; +using Neo.Wallets; using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; namespace Neo.CLI { partial class MainService { + private class AttachAsset + { + public AssetDescriptor Asset; + public BigDecimal Amount; + + /// + /// Parse from string + /// Format: neo=1 gas=2.456 0x0..=123.5 + /// + /// Input + /// + internal static AttachAsset Parse(string input) + { + var split = input.Split('=', StringSplitOptions.RemoveEmptyEntries); + if (split.Length != 2) throw new FormatException("Format expected: neo=1"); + + var ret = new AttachAsset + { + Asset = (split[0].ToLowerInvariant()) switch + { + "neo" => new AssetDescriptor(NativeContract.NEO.Hash), + "gas" => new AssetDescriptor(NativeContract.GAS.Hash), + _ => new AssetDescriptor(UInt160.Parse(split[0])), + } + }; + + ret.Amount = BigDecimal.Parse(split[1], ret.Asset.Decimals); + return ret; + } + } + /// /// Process "deploy" command /// @@ -48,8 +81,9 @@ private void OnDeployCommand(string filePath, string manifestPath = null) /// Operation /// Contract parameters /// Witness address + /// Attach [ConsoleCommand("invoke", Category = "Contract Commands")] - private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null) + private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null, AttachAsset[] attach = null) { List parameters = new List(); List signCollection = new List(); @@ -95,6 +129,54 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contra using (ScriptBuilder scriptBuilder = new ScriptBuilder()) { + if (attach != null) + { + if (NoWallet()) return; + + foreach (var entry in attach.GroupBy(u => u.Asset.AssetId)) + { + // Get amount + + var amount = BigInteger.Zero; + foreach (var am in entry) amount += am.Amount.Value; + + // Find a valid sender + + var tempTx = CurrentWallet.MakeTransaction(new[] + { + new TransferOutput + { + AssetId = entry.Key, + Value = new BigDecimal(amount, entry.First().Asset.Decimals), + ScriptHash = scriptHash + } + }); + + if (tempTx == null) + { + Console.WriteLine("Insufficient funds of: " + entry.First().Asset.AssetName); + return; + } + + // Append at the begining the right script + + scriptBuilder.EmitAppCall(entry.Key, "transfer", tempTx.Sender, scriptHash, amount); + + // Compute new cosigners + + signCollection.Add(new Cosigner() + { + Account = tempTx.Sender, + AllowedContracts = new UInt160[] { entry.Key }, + Scopes = WitnessScope.CustomContracts + }); + } + + // Add new cosigners + + tx.Cosigners = signCollection.ToArray(); + } + scriptBuilder.EmitAppCall(scriptHash, operation, parameters.ToArray()); tx.Script = scriptBuilder.ToArray(); Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'"); diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs index f543dba16..ac2891c66 100644 --- a/neo-cli/CLI/MainService.cs +++ b/neo-cli/CLI/MainService.cs @@ -115,6 +115,7 @@ public MainService() : base() RegisterCommandHander((str) => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray()); RegisterCommandHander((str) => JObject.Parse(str)); RegisterCommandHander((obj) => (JArray)obj); + RegisterCommandHander((str) => str.Select(u => AttachAsset.Parse(u)).ToArray()); RegisterCommand(this);