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

Update deploy command following NEO3 schema #463

Merged
merged 13 commits into from
Oct 18, 2019
74 changes: 62 additions & 12 deletions neo-cli/Shell/MainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,9 @@ private bool OnBroadcastCommand(string[] args)
private bool OnDeployCommand(string[] args)
{
if (NoWallet()) return true;
byte[] script = LoadDeploymentScript(
/* filePath */ args[1],
/* hasStorage */ args[2].ToBool(),
/* isPayable */ args[3].ToBool(),
byte[] script = LoadDeploymentScript(
/* filePath */ args[1],
/* manifest */ args.Length == 2 ? "" : args[2],
/* scriptHash */ out var scriptHash);

Transaction tx;
Expand Down Expand Up @@ -219,9 +218,26 @@ private bool OnInvokeCommand(string[] args)
return SignAndSendTx(tx);
}

private byte[] LoadDeploymentScript(string nefFilePath, bool hasStorage, bool isPayable, out UInt160 scriptHash)
private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, out UInt160 scriptHash)
{
var info = new FileInfo(nefFilePath);
if (string.IsNullOrEmpty(manifestFilePath))
{
manifestFilePath = Path.ChangeExtension(nefFilePath, ".manifest.json");
}

// Read manifest

var info = new FileInfo(manifestFilePath);
if (!info.Exists || info.Length >= Transaction.MaxTransactionSize)
{
throw new ArgumentException(nameof(manifestFilePath));
}

var manifest = ContractManifest.Parse(File.ReadAllText(manifestFilePath));

// Read nef

info = new FileInfo(nefFilePath);
if (!info.Exists || info.Length >= Transaction.MaxTransactionSize)
{
throw new ArgumentException(nameof(nefFilePath));
Expand All @@ -232,14 +248,48 @@ private byte[] LoadDeploymentScript(string nefFilePath, bool hasStorage, bool is
{
file = stream.ReadSerializable<NefFile>();
}
scriptHash = file.ScriptHash;

ContractFeatures properties = ContractFeatures.NoProperty;
if (hasStorage) properties |= ContractFeatures.HasStorage;
if (isPayable) properties |= ContractFeatures.Payable;
// Basic script checks

using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true))
{
var context = engine.LoadScript(file.Script);

while (context.InstructionPointer <= context.Script.Length)
{
// Check bad opcodes

var ci = context.CurrentInstruction;

if (ci == null || !Enum.IsDefined(typeof(OpCode), ci.OpCode))
{
throw new FormatException($"OpCode not found at {context.InstructionPointer}-{((byte)ci.OpCode).ToString("x2")}");
}

switch (ci.OpCode)
{
case OpCode.SYSCALL:
{
// Check bad syscalls (NEO2)

if (!InteropService.SupportedMethods().ContainsKey(ci.TokenU32))
{
throw new FormatException($"Syscall not found {ci.TokenU32.ToString("x2")}. Are you using a NEO2 smartContract?");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed, @shargon?

The compiler is going to be different.
Maybe we can just say that the syscall is not valid. I think there is not need to really explicit that it is NEO2.

Copy link
Member

@superboyiii superboyiii Sep 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vncoelho Hey, my friend, since we've not deployed a new nuget for NEO3 SmartContract Framework, and the NEO3 one is also using the version number 2.9.3, it can make developers greatly confused, including me, hahaha. So I think this error message is necessary because if you're using the NEO2 nuget of Framework 2.9.3 to deploy a sc on NEO3, it's incompatible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, If you use the old version of SmartContract.Framework, you can get a wrong NEF, so I think that this checks could be very useful. Is possible that some invalid contract pass, it is a basic filter for prevent some human errors.

}
break;
}
}

context.InstructionPointer += ci.Size;
}
}

// Build script

scriptHash = file.ScriptHash;
using (ScriptBuilder sb = new ScriptBuilder())
{
sb.EmitSysCall(InteropService.Neo_Contract_Create, file.Script, properties);
sb.EmitSysCall(InteropService.Neo_Contract_Create, file.Script, manifest.ToJson().ToString());
return sb.ToArray();
}
}
Expand Down Expand Up @@ -572,7 +622,7 @@ private bool OnHelpCommand(string[] args)
"\tsend <id|alias> <address> <value>\n" +
"\tsign <jsonObjectToSign>\n" +
"Contract Commands:\n" +
"\tdeploy <nefFilePath> <hasStorage (true|false)> <isPayable (true|false)\n" +
"\tdeploy <nefFilePath> [manifestFile]\n" +
"\tinvoke <scripthash> <command> [optionally quoted params separated by space]\n" +
"Node Commands:\n" +
"\tshow state\n" +
Expand Down