Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge #2

Merged
merged 10 commits into from
Oct 15, 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
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
run: dotnet test tests/Neo.Compiler.MSIL.UnitTests /p:CollectCoverage=true /p:CoverletOutput=${GITHUB_WORKSPACE}/coverage/ /p:Exclude=\"[Neo.SmartContract.*]*,[Neo.Compiler.MSIL.UnitTests]*,[Neo.Compiler.MSIL.UnitTests.*]*\"
- name: Test Neo.SmartContract.Framework.UnitTests
run: dotnet test tests/Neo.SmartContract.Framework.UnitTests /p:CollectCoverage=true /p:CoverletOutput=${GITHUB_WORKSPACE}/coverage/lcov /p:MergeWith=${GITHUB_WORKSPACE}/coverage/coverage.json /p:Exclude=\"[Neo.SmartContract.*]*,[Neo.Compiler.MSIL.UnitTests]*,[Neo.Compiler.MSIL.UnitTests.*]*\" /p:CoverletOutputFormat=lcov
- name: Test Template.NEP5.UnitTests
run: dotnet test tests/Template.NEP5.UnitTests /p:CollectCoverage=true /p:CoverletOutput=${GITHUB_WORKSPACE}/coverage/lcov /p:MergeWith=${GITHUB_WORKSPACE}/coverage/coverage.json /p:Exclude=\"[Neo.SmartContract.*]*,[Neo.Compiler.MSIL.UnitTests]*,[Neo.Compiler.MSIL.UnitTests.*]*\" /p:CoverletOutputFormat=lcov
- name: Coveralls
uses: coverallsapp/github-action@master
with:
Expand Down
3 changes: 3 additions & 0 deletions neo-devpack-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D5266066-0AFD-44D5-A83E-2F73668A63C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.NEP5.CSharp", "templates\Template.NEP5.CSharp\Template.NEP5.CSharp.csproj", "{ADD05222-DC45-4FDC-A41A-30A97BACC95F}"
ProjectSection(ProjectDependencies) = postProject
{42C0FF0F-0A7C-4166-A773-1F944642C209} = {42C0FF0F-0A7C-4166-A773-1F944642C209}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.NEP5.UnitTests", "tests\Template.NEP5.UnitTests\Template.NEP5.UnitTests.csproj", "{780141EE-D6E9-4591-8470-8F91B12027CA}"
EndProject
Expand Down
5 changes: 3 additions & 2 deletions src/Neo.Compiler.MSIL/FuncExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Neo.Compiler
public class FuncExport
{
public static readonly TypeReference Void = new TypeReference("System", "Void", ModuleDefinition.ReadModule(typeof(object).Assembly.Location, new ReaderParameters(ReadingMode.Immediate)), null);
public static readonly TypeReference Boolean = new TypeReference("System", "Boolean", ModuleDefinition.ReadModule(typeof(object).Assembly.Location, new ReaderParameters(ReadingMode.Immediate)), null);

internal static string ConvType(TypeReference t)
{
Expand Down Expand Up @@ -176,7 +177,7 @@ private static object BuildSupportedStandards(Mono.Collections.Generic.Collectio
return extra;
}

private static string BuildExtraAttributes(List<Mono.Collections.Generic.Collection<CustomAttributeArgument>> extraAttributes)
private static string BuildExtraAttributes(ICollection<Mono.Collections.Generic.Collection<CustomAttributeArgument>> extraAttributes)
{
if (extraAttributes == null || extraAttributes.Count == 0)
{
Expand Down Expand Up @@ -210,7 +211,7 @@ public static string GenerateManifest(JObject abi, NeoModule module)
.Select(u => (ContractFeatures)u.ConstructorArguments.FirstOrDefault().Value)
.FirstOrDefault();

var extraAttributes = module == null ? new List<Mono.Collections.Generic.Collection<CustomAttributeArgument>>() : module.attributes.Where(u => u.AttributeType.FullName == "Neo.SmartContract.Framework.ManifestExtraAttribute").Select(attribute => attribute.ConstructorArguments).ToList();
var extraAttributes = module == null ? Array.Empty<Mono.Collections.Generic.Collection<CustomAttributeArgument>>() : module.attributes.Where(u => u.AttributeType.FullName == "Neo.SmartContract.Framework.ManifestExtraAttribute").Select(attribute => attribute.ConstructorArguments).ToArray();
var supportedStandardsAttribute = module?.attributes.Where(u => u.AttributeType.FullName == "Neo.SmartContract.Framework.SupportedStandardsAttribute").Select(attribute => attribute.ConstructorArguments).FirstOrDefault();

var extra = BuildExtraAttributes(extraAttributes);
Expand Down
77 changes: 72 additions & 5 deletions src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Mono.Cecil;
using Neo.SmartContract;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;

Expand Down Expand Up @@ -644,12 +646,52 @@ private int ConvertCall(OpCode src, NeoMethod to)
}
else if (src.tokenMethod.Contains("::Concat("))
{
//"System.String System.String::Concat(System.String,System.String)"
Convert1by1(VM.OpCode.CAT, src, to);
//String::Concat has many overload, we can only support part of them.
if (src.tokenMethod == "System.String System.String::Concat(System.String,System.String)")
{
Convert1by1(VM.OpCode.CAT, src, to);
}
else if (src.tokenMethod == "System.String System.String::Concat(System.String,System.String,System.String)")
{
Convert1by1(VM.OpCode.CAT, src, to);
Insert1(VM.OpCode.CAT, "", to);
}
else if (src.tokenMethod == "System.String System.String::Concat(System.String,System.String,System.String,System.String)")
{
Convert1by1(VM.OpCode.CAT, src, to);
Insert1(VM.OpCode.CAT, "", to);
Insert1(VM.OpCode.CAT, "", to);
}
else if (src.tokenMethod == "System.String System.String::Concat(System.String[])")
{
//unpack array
Convert1by1(VM.OpCode.UNPACK, src, to);

//loops
var loopaddr = this.addr;
Insert1(VM.OpCode.DUP, "", to); //+1
Insert1(VM.OpCode.PUSH1, "", to);//+1
Insert1(VM.OpCode.JMPLE_L, "", to, BitConverter.GetBytes((int)5 + 9));//+5 to end
Insert1(VM.OpCode.DEC, "", to);//+1
Insert1(VM.OpCode.REVERSE3, "", to);//+1
Insert1(VM.OpCode.CAT, "", to);//+1
Insert1(VM.OpCode.SWAP, "", to);//+1
var addrreset = loopaddr - this.addr;

Insert1(VM.OpCode.JMP_L, "", to, BitConverter.GetBytes((int)addrreset));//+5 to loops

//:endpos

Insert1(VM.OpCode.DROP, "", to);
}
else
{
throw new Exception("not support this overload:" + src.tokenMethod);
}

Insert1(VM.OpCode.CONVERT, "", to, new byte[] { (byte)VM.Types.StackItemType.ByteString });
return 0;
}

else if (src.tokenMethod == "System.String System.String::Substring(System.Int32,System.Int32)")
{
Convert1by1(VM.OpCode.SUBSTR, src, to);
Expand Down Expand Up @@ -837,8 +879,7 @@ private int ConvertCall(OpCode src, NeoMethod to)
Convert1by1(VM.OpCode.PACK, null, to);

// Push call method name, the first letter should be lowercase.
var methodName = defs.Body.Method.Name;
ConvertPushString(methodName[..1].ToLowerInvariant() + methodName[1..], src, to);
ConvertPushString(GetMethodName(defs.Body.Method), src, to);

// Push contract hash.
ConvertPushDataArray(callhash, src, to);
Expand Down Expand Up @@ -882,6 +923,32 @@ private int ConvertCall(OpCode src, NeoMethod to)
return 0;
}

private string GetMethodName(MethodDefinition method)
{
foreach (var attr in method.CustomAttributes)
{
if (attr.AttributeType.Name == nameof(DisplayNameAttribute))
{
return (string)attr.ConstructorArguments[0].Value;
}
}

string methodName = null;
if (method.SemanticsAttributes.HasFlag(MethodSemanticsAttributes.Getter))
{
foreach (PropertyDefinition property in method.DeclaringType.Properties)
{
if (property.GetMethod == method)
{
methodName = property.Name;
break;
}
}
}
if (methodName is null) methodName = method.Name;
return methodName[..1].ToLowerInvariant() + methodName[1..];
}

private List<string> GetAllConstStringAfter(ILMethod method, OpCode src)
{
List<string> strlist = new List<string>();
Expand Down
3 changes: 2 additions & 1 deletion src/Neo.Compiler.MSIL/MSIL/ILModule.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.ComponentModel;

/// <summary>
/// This file is responsible for the parsing of the IL DLL. The core parsing is using mono.cecil, which is prearranged to make it easier to use
Expand Down Expand Up @@ -121,7 +122,7 @@ public ILField(ILType type, FieldDefinition field)
Mono.Collections.Generic.Collection<CustomAttribute> ca = ev.CustomAttributes;
foreach (var attr in ca)
{
if (attr.AttributeType.Name == "DisplayNameAttribute")
if (attr.AttributeType.Name == nameof(DisplayNameAttribute))
{
this.displayName = (string)attr.ConstructorArguments[0].Value;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="3.4.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
<PackageReference Include="Neo" Version="3.0.0-CI01001" />
<PackageReference Include="Neo" Version="3.0.0-CI01036" />
</ItemGroup>

<ItemGroup>
Expand Down
24 changes: 24 additions & 0 deletions src/Neo.Compiler.MSIL/NeoModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,30 @@ public NeoMethod(ILMethod method)
{
ProcessAttribute(attr);
}

// Ensure method definition

switch (displayName)
{
case StandardMethods.Verify:
{
if (method.returntype.FullName != FuncExport.Boolean.FullName)
{
throw new Exception("verify must be: bool verify(...);");
}
break;
}
case StandardMethods.Deploy:
{
if (method.paramtypes.Count != 1 ||
method.returntype.FullName != FuncExport.Void.FullName ||
method.paramtypes[0].type.FullName != FuncExport.Boolean.FullName)
{
throw new Exception("_deploy must be: void _deploy(bool update);");
}
break;
}
}
}

private void ProcessAttribute(CustomAttribute attr)
Expand Down
8 changes: 8 additions & 0 deletions src/Neo.Compiler.MSIL/StandardMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Neo.Compiler
{
internal static class StandardMethods
{
public const string Verify = "verify";
public const string Deploy = "_deploy";
}
}
40 changes: 40 additions & 0 deletions src/Neo.SmartContract.Framework/List.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace Neo.SmartContract.Framework
{
public class List<T>
{
[OpCode(OpCode.NEWARRAY0)]
public extern List();

public extern int Count
{
[OpCode(OpCode.SIZE)]
get;
}

public extern T this[int key]
{
[OpCode(OpCode.PICKITEM)]
get;
[OpCode(OpCode.SETITEM)]
set;
}

[OpCode(OpCode.APPEND)]
public extern void Add(T item);

[OpCode(OpCode.REMOVE)]
public extern void RemoveAt(int index);

[OpCode(OpCode.CLEARITEMS)]
public extern void Clear();

[OpCode(OpCode.VALUES)]
public extern List<T> Clone();

[Script]
public static extern implicit operator List<T>(T[] array);

[Script]
public static extern implicit operator T[](List<T> array);
}
}
9 changes: 9 additions & 0 deletions src/Neo.SmartContract.Framework/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ public class Map<TKey, TValue>
[OpCode(OpCode.NEWMAP)]
public extern Map();

public extern int Count
{
[OpCode(OpCode.SIZE)]
get;
}

public extern TValue this[TKey key]
{
[OpCode(OpCode.PICKITEM)]
Expand All @@ -13,6 +19,9 @@ public extern TValue this[TKey key]
set;
}

[OpCode(OpCode.CLEARITEMS)]
public extern void Clear();

public extern TKey[] Keys
{
[OpCode(OpCode.KEYS)]
Expand Down
11 changes: 11 additions & 0 deletions src/Neo.SmartContract.Framework/Services/Neo/Designation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma warning disable CS0626

namespace Neo.SmartContract.Framework.Services.Neo
{
[Contract("0x763afecf3ebba0a67568a2c8be06e8f068c62666")]
public class Designation
{
public static extern string Name { get; }
public static extern byte[][] GetDesignatedByRole(DesignationRole role);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Neo.SmartContract.Framework.Services.Neo
{
public enum DesignationRole : byte
{
StateValidator = 4,
Oracle = 8
}
}
6 changes: 3 additions & 3 deletions src/Neo.SmartContract.Framework/Services/Neo/GAS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ namespace Neo.SmartContract.Framework.Services.Neo
[Contract("0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc")]
public class GAS
{
public static extern string Name();
public static extern string Symbol();
public static extern byte Decimals();
public static extern string Name { get; }
public static extern string Symbol { get; }
public static extern byte Decimals { get; }
public static extern BigInteger TotalSupply();
public static extern BigInteger BalanceOf(byte[] account);
}
Expand Down
7 changes: 3 additions & 4 deletions src/Neo.SmartContract.Framework/Services/Neo/NEO.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#pragma warning disable CS0626

using System;
using System.Numerics;

namespace Neo.SmartContract.Framework.Services.Neo
{
[Contract("0xde5f57d430d3dece511cf975a8d37848cb9e0525")]
public class NEO
{
public static extern string Name();
public static extern string Symbol();
public static extern BigInteger Decimals();
public static extern string Name { get; }
public static extern string Symbol { get; }
public static extern byte Decimals { get; }
public static extern BigInteger TotalSupply();
public static extern BigInteger BalanceOf(byte[] account);

Expand Down
11 changes: 11 additions & 0 deletions src/Neo.SmartContract.Framework/Services/Neo/Oracle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma warning disable CS0626

namespace Neo.SmartContract.Framework.Services.Neo
{
[Contract("0x3c05b488bf4cf699d0631bf80190896ebbf38c3b")]
public class Oracle
{
public static extern string Name { get; }
public static extern void Request(string url, string filter, string callback, object userData, long gasForResponse);
}
}
34 changes: 32 additions & 2 deletions templates/Template.CSharp/Contract1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,40 @@ namespace $safeprojectname$
[Features(ContractFeatures.HasStorage)]
public class Contract1 : SmartContract
{
public static bool Main()
//TODO: Replace it with your own address.
static readonly byte[] Owner = "NiNmXL8FjEUEs1nfX9uHFBNaenxDHJtmuB".ToScriptHash();

private static bool IsOwner() => Runtime.CheckWitness(Owner);

// When this contract address is included in the transaction signature,
// this method will be triggered as a VerificationTrigger to verify that the signature is correct.
// For example, this method needs to be called when withdrawing token from the contract.
public static bool Verify() => IsOwner();

// TODO: Replace it with your methods.
public static byte[] MyMethod()
{
return Storage.Get("Hello");
}

public static void _deploy(bool update)
{
if (update) return;

// It will be executed during deploy
Storage.Put("Hello", "World");
return true;
}

public static void Update(byte[] script, string manifest)
{
if (!IsOwner()) throw new Exception("No authorization.");
Contract.Update(script, manifest);
}

public static void Destroy()
{
if (!IsOwner()) throw new Exception("No authorization.");
Contract.Destroy();
}
}
}
Loading