Skip to content
This repository has been archived by the owner on Dec 7, 2023. It is now read-only.

Allow smart contract verification #628

Merged
merged 20 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions neo-cli/CLI/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@ namespace Neo.CLI
{
internal static class Helper
{
public static bool ToBool(this string input)
{
if (input == null) return false;

input = input.ToLowerInvariant();

return input == "true" || input == "yes" || input == "1";
}

public static bool IsYes(this string input)
{
if (input == null) return false;
Expand Down
29 changes: 20 additions & 9 deletions neo-cli/CLI/MainService.Contracts.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
using Neo.ConsoleService;
using Neo.IO.Json;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.VM;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Neo.CLI
Expand Down Expand Up @@ -47,13 +42,29 @@ private void OnDeployCommand(string filePath, string manifestPath = null)
/// <param name="scriptHash">Script hash</param>
/// <param name="operation">Operation</param>
/// <param name="contractParameters">Contract parameters</param>
/// <param name="witnessAddress">Witness address</param>
/// <param name="sender">Transaction's sender</param>
/// <param name="signerAccounts">Signer's accounts</param>
[ConsoleCommand("invoke", Category = "Contract Commands")]
private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] signerAccounts = null)
private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160 sender = null, UInt160[] signerAccounts = null)
{
Signer[] signers = Array.Empty<Signer>();
if (signerAccounts != null && !NoWallet())
signers = CurrentWallet.GetAccounts().Where(p => !p.Lock && !p.WatchOnly && signerAccounts.Contains(p.ScriptHash)).Select(p => new Signer() { Account = p.ScriptHash, Scopes = WitnessScope.CalledByEntry }).ToArray();
{
if (sender != null)
{
if (signerAccounts.Contains(sender) && signerAccounts[0] != sender)
{
var signersList = signerAccounts.ToList();
signersList.Remove(sender);
signerAccounts = signersList.Prepend(sender).ToArray();
}
else if (!signerAccounts.Contains(sender))
{
signerAccounts = signerAccounts.Prepend(sender).ToArray();
}
}
signers = signerAccounts.Select(p => new Signer() { Account = p, Scopes = WitnessScope.CalledByEntry }).ToArray();
}

Transaction tx = new Transaction
{
Expand All @@ -66,7 +77,7 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contra
if (NoWallet()) return;
try
{
tx = CurrentWallet.MakeTransaction(tx.Script, signers.Length > 0 ? signers[0].Account : null, signers);
tx = CurrentWallet.MakeTransaction(tx.Script, sender, signers);
}
catch (InvalidOperationException e)
{
Expand Down
12 changes: 10 additions & 2 deletions neo-cli/CLI/MainService.NEP5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Neo.Wallets;
using System;
using System.Globalization;
using System.Linq;

namespace Neo.CLI
{
Expand All @@ -17,8 +18,9 @@ partial class MainService
/// <param name="to">To</param>
/// <param name="amount">Ammount</param>
/// <param name="from">From</param>
/// <param name="signersAccounts">Signer's accounts</param>
[ConsoleCommand("transfer", Category = "NEP5 Commands")]
private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount, UInt160 from = null)
private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount, UInt160 from = null, UInt160[] signersAccounts = null)
{
var asset = new AssetDescriptor(tokenHash);
var value = BigDecimal.Parse(amount.ToString(CultureInfo.InvariantCulture), asset.Decimals);
Expand All @@ -36,7 +38,13 @@ private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount, UI
Value = value,
ScriptHash = to
}
}, from: from);
}, from: from, cosigners: signersAccounts?.Select(p => new Signer
{
// default access for transfers should be valid only for first invocation
Scopes = WitnessScope.CalledByEntry,
Account = p
})
.ToArray() ?? new Signer[0]);
}
catch (InvalidOperationException e)
{
Expand Down
88 changes: 77 additions & 11 deletions neo-cli/CLI/MainService.Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,10 @@ private void OnExportKeyCommand(string path = null, UInt160 scriptHash = null)
if (scriptHash == null)
keys = CurrentWallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey());
else
keys = new[] { CurrentWallet.GetAccount(scriptHash).GetKey() };
{
var account = CurrentWallet.GetAccount(scriptHash);
keys = account?.HasKey != true ? Array.Empty<KeyPair>() : new[] { account.GetKey() };
}
if (path == null)
foreach (KeyPair key in keys)
Console.WriteLine(key.Export());
Expand Down Expand Up @@ -284,6 +287,56 @@ private void OnImportKeyCommand(string wifOrFile)
wallet.Save();
}

/// <summary>
/// Process "import watchonly" command
/// </summary>
[ConsoleCommand("import watchonly", Category = "Wallet Commands")]
private void OnImportWatchOnlyCommand(string addressOrFile)
{
UInt160 address = null;
try
{
address = StringToAddress(addressOrFile);
}
catch (FormatException) { }
if (address is null)
{
var fileInfo = new FileInfo(addressOrFile);

if (!fileInfo.Exists)
{
Console.WriteLine($"Error: File '{fileInfo.FullName}' doesn't exists");
return;
}

if (fileInfo.Length > 1024 * 1024)
{
if (!ReadUserInput($"The file '{fileInfo.FullName}' is too big, do you want to continue? (yes|no)", false).IsYes())
{
return;
}
}

string[] lines = File.ReadAllLines(fileInfo.FullName).Where(u => !string.IsNullOrEmpty(u)).ToArray();
using (var percent = new ConsolePercent(0, lines.Length))
{
for (int i = 0; i < lines.Length; i++)
{
address = StringToAddress(lines[i]);
CurrentWallet.CreateAccount(address);
percent.Value++;
}
}
}
else
{
WalletAccount account = CurrentWallet.CreateAccount(address);
Console.WriteLine($"Address: {account.Address}");
}
if (CurrentWallet is NEP6Wallet wallet)
wallet.Save();
}

/// <summary>
/// Process "list address" command
/// </summary>
Expand All @@ -294,25 +347,30 @@ private void OnListAddressCommand()

using (var snapshot = Blockchain.Singleton.GetSnapshot())
{
foreach (Contract contract in CurrentWallet.GetAccounts().Where(p => !p.WatchOnly).Select(p => p.Contract))
foreach (var account in CurrentWallet.GetAccounts())
{
var contract = account.Contract;
var type = "Nonstandard";

if (contract.Script.IsMultiSigContract())
if (account.WatchOnly)
{
type = "WatchOnly";
}
else if (contract.Script.IsMultiSigContract())
{
type = "MultiSignature";
}
else if (contract.Script.IsSignatureContract())
{
type = "Standard";
}
else if (snapshot.Contracts.TryGet(contract.ScriptHash) != null)
else if (snapshot.Contracts.TryGet(account.ScriptHash) != null)
{
type = "Deployed-Nonstandard";
}

Console.WriteLine($"{" Address: "}{contract.Address}\t{type}");
Console.WriteLine($"{"ScriptHash: "}{contract.ScriptHash}\n");
Console.WriteLine($"{" Address: "}{account.Address}\t{type}");
Console.WriteLine($"{"ScriptHash: "}{account.ScriptHash}\n");
}
}
}
Expand Down Expand Up @@ -345,10 +403,11 @@ private void OnListAssetCommand()
private void OnListKeyCommand()
{
if (NoWallet()) return;
foreach (KeyPair key in CurrentWallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey()))
foreach (WalletAccount account in CurrentWallet.GetAccounts().Where(p => p.HasKey))
{
Console.WriteLine($" Address: {Contract.CreateSignatureContract(key.PublicKey).Address}");
Console.WriteLine($"PublicKey: {key.PublicKey}\n");
Console.WriteLine($" Address: {account.Address}");
Console.WriteLine($"ScriptHash: {account.ScriptHash}");
Console.WriteLine($" PublicKey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}\n");
}
}

Expand Down Expand Up @@ -389,8 +448,9 @@ private void OnSignCommand(JObject jsonObjectToSign)
/// <param name="to">To</param>
/// <param name="amount">Amount</param>
/// <param name="from">From</param>
/// <param name="signerAccounts">Signer's accounts</param>
[ConsoleCommand("send", Category = "Wallet Commands")]
private void OnSendCommand(UInt160 asset, UInt160 to, string amount, UInt160 from = null)
private void OnSendCommand(UInt160 asset, UInt160 to, string amount, UInt160 from = null, UInt160[] signerAccounts = null)
{
if (NoWallet()) return;
string password = ReadUserInput("password", true);
Expand Down Expand Up @@ -422,7 +482,13 @@ private void OnSendCommand(UInt160 asset, UInt160 to, string amount, UInt160 fro
Value = decimalAmount,
ScriptHash = to
}
}, from: from);
}, from: from, cosigners: signerAccounts?.Select(p => new Signer
{
// default access for transfers should be valid only for first invocation
Scopes = WitnessScope.CalledByEntry,
Account = p
})
.ToArray() ?? new Signer[0]);
}
catch (Exception e)
{
Expand Down
49 changes: 23 additions & 26 deletions neo-cli/CLI/MainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,30 +90,7 @@ public MainService() : base()

RegisterCommandHander<string, UInt256>(false, (str) => UInt256.Parse(str));
RegisterCommandHander<string[], UInt256[]>((str) => str.Select(u => UInt256.Parse(u.Trim())).ToArray());
RegisterCommandHander<string[], UInt160[]>((arr) =>
{
return arr.Select(str =>
{
switch (str.ToLowerInvariant())
{
case "neo": return NativeContract.NEO.Hash;
case "gas": return NativeContract.GAS.Hash;
}

// Try to parse as UInt160

if (UInt160.TryParse(str, out var addr))
{
return addr;
}

// Accept wallet format

return str.ToScriptHash();
})
.ToArray();
});

RegisterCommandHander<string[], UInt160[]>((arr) => arr.Select(str => StringToAddress(str)).ToArray());
RegisterCommandHander<string, ECPoint>((str) => ECPoint.Parse(str.Trim(), ECCurve.Secp256r1));
RegisterCommandHander<string[], ECPoint[]>((str) => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray());
RegisterCommandHander<string, JObject>((str) => JObject.Parse(str));
Expand All @@ -123,6 +100,26 @@ public MainService() : base()
RegisterCommand(this);
}

internal static UInt160 StringToAddress(string input)
{
switch (input.ToLowerInvariant())
{
case "neo": return NativeContract.NEO.Hash;
case "gas": return NativeContract.GAS.Hash;
}

// Try to parse as UInt160

if (UInt160.TryParse(input, out var addr))
{
return addr;
}

// Accept wallet format

return input.ToScriptHash();
}

public override void RunConsole()
{
Console.ForegroundColor = ConsoleColor.DarkGreen;
Expand Down Expand Up @@ -485,7 +482,7 @@ private void SendTransaction(byte[] script, UInt160 account = null)
Transaction tx = CurrentWallet.MakeTransaction(script, account, signers);
Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");

using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, null, testMode: true))
using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, container: tx))
{
PrintExecutionOutput(engine, true);
if (engine.State == VMState.FAULT) return;
Expand Down Expand Up @@ -540,7 +537,7 @@ private StackItem OnInvokeWithResult(UInt160 scriptHash, string operation, IVeri
tx.Script = script;
}

using ApplicationEngine engine = ApplicationEngine.Run(script, verificable, testMode: true);
using ApplicationEngine engine = ApplicationEngine.Run(script, container: verificable);
PrintExecutionOutput(engine, showStack);
return engine.State == VMState.FAULT ? null : engine.ResultStack.Peek();
}
Expand Down
2 changes: 1 addition & 1 deletion neo-cli/neo-cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Neo" Version="3.0.0-preview3-00" />
<PackageReference Include="Neo" Version="3.0.0-CI00998" />
</ItemGroup>

<ItemGroup>
Expand Down