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

Add UInt160, UInt256 and ECPoint to SmartContract Framework #362

Merged
merged 44 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
89dcd8c
introduce reference alias
Sep 18, 2020
7522579
scfx alias for unit tests
Sep 18, 2020
30ad962
introduce UInt160/256 + ECPoint for scfx
Sep 18, 2020
4f85872
strongly typed framework methods (tests failing)
Sep 18, 2020
e6c3724
modifed IsContractCall to return Uint160
Sep 18, 2020
b69471a
strongly typed NEP5 template (tests not passing)
Sep 18, 2020
410e277
neon tests passing
Sep 18, 2020
d9aedea
NativeContractHash property support
Sep 18, 2020
7d5902b
All tests working
Sep 18, 2020
983b822
NativeContractHashAttribute new file
Sep 18, 2020
d83b18f
remove ValidateAddress from NEP5 contract template
Sep 18, 2020
c89da42
non-static construction of UInt160/256 working. Static construction f…
Sep 18, 2020
1340354
UInt160/256 Zero property
Sep 19, 2020
f638bcb
byte array ctors for uint160/256
Sep 19, 2020
7953f7d
assorted cleanup
Sep 19, 2020
ad7da01
dotnet format
Sep 19, 2020
215f212
Merge branch 'master' into devhawk/unify1
Sep 20, 2020
c26ea9f
Merge branch 'master' into devhawk/unify1
devhawk Sep 21, 2020
b65bc48
remove default ctor for UInt160/256
Sep 22, 2020
84e4423
remove UInt160/256 code from ConvertNewObj
Sep 22, 2020
eade0db
replace byte array ctors with explicit casts + move script logic out …
Sep 22, 2020
9b3f1de
dotnet format
Sep 22, 2020
d36414a
Merge remote-tracking branch 'upstream/HEAD' into devhawk/unify1
Sep 22, 2020
2347736
PUSHDATA1 -> PUSHINT8 CR feedback
Sep 23, 2020
c97e49d
ContractHashAttribute CR feedback
Sep 23, 2020
8c88a2b
Merge branch 'master' into devhawk/unify1
Sep 24, 2020
e852318
add convert opcode to explicit byte[] conversion operators
Sep 25, 2020
3907dea
Merge branch 'master' into devhawk/unify1
devhawk Oct 5, 2020
e9426ea
Merge branch 'master' into devhawk/unify1
Oct 20, 2020
3867b6e
CR Feedback
Oct 22, 2020
0e3e976
Merge branch 'master' into devhawk/unify1
Oct 23, 2020
8c2d930
Remove double enter
shargon Oct 26, 2020
051eb6d
Merge branch 'master' into devhawk/unify1
shargon Oct 27, 2020
41d51d4
Add IsEmpty
shargon Oct 29, 2020
1c7f1f6
is empty -> is zero
Nov 2, 2020
d7509e3
add bytestring conversion operators
Nov 2, 2020
8fed1bf
ValidateAddress
Nov 2, 2020
0648bc4
Clean enters
shargon Nov 3, 2020
11362bc
Update ContractHashAttribute.cs
shargon Nov 4, 2020
d9900a5
Update src/Neo.SmartContract.Framework/ECPoint.cs
devhawk Nov 5, 2020
d995892
remove redundant bytestring convert opcodes
Nov 5, 2020
f0bee43
remove unneeded convert opcodes
Nov 6, 2020
992dae7
explicit byte[] operator for uint160/256
Nov 6, 2020
d84351b
format
erikzhang Nov 8, 2020
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
5 changes: 4 additions & 1 deletion src/Neo.Compiler.MSIL/Compiler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
extern alias scfx;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.VisualBasic;
Expand All @@ -7,6 +9,7 @@
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using scfxSmartContract = scfx.Neo.SmartContract.Framework.SmartContract;

namespace Neo.Compiler
{
Expand Down Expand Up @@ -200,7 +203,7 @@ private static MetadataReference[] CreateReferences(params string[] references)
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Runtime.Numerics.dll")),
MetadataReference.CreateFromFile(typeof(System.ComponentModel.DisplayNameAttribute).Assembly.Location),
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(SmartContract.Framework.SmartContract).Assembly.Location),
MetadataReference.CreateFromFile(typeof(scfxSmartContract).Assembly.Location),
});
refs.AddRange(references.Where(u => u != "Neo.SmartContract.Framework.dll").Select(u => MetadataReference.CreateFromFile(u)));
return refs.ToArray();
Expand Down
8 changes: 7 additions & 1 deletion src/Neo.Compiler.MSIL/FuncExport.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
extern alias scfx;

using Mono.Cecil;
using Neo.IO.Json;
using Neo.SmartContract.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IApiInterface = scfx.Neo.SmartContract.Framework.IApiInterface;
using ContractFeatures = scfx.Neo.SmartContract.Framework.ContractFeatures;

namespace Neo.Compiler
{
Expand Down Expand Up @@ -47,6 +50,9 @@ internal static string ConvType(TypeReference t)
case "IInteropInterface": return "InteropInterface";
case "System.Void": return "Void";
case "System.Object": return "Any";
case "Neo.UInt160": return "Hash160";
case "Neo.UInt256": return "Hash256";
case "Neo.Cryptography.ECC.ECPoint": return "PublicKey";
}

if (t.IsArray) return "Array";
Expand Down
55 changes: 29 additions & 26 deletions src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Mono.Cecil;
using Neo.IO;
using Neo.SmartContract;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -164,7 +165,7 @@ public bool IsSysCall(Mono.Cecil.MethodDefinition defs, out string name)
}
*/

public bool IsContractCall(Mono.Cecil.MethodDefinition defs, out byte[] hash)
public bool IsContractCall(Mono.Cecil.MethodDefinition defs, out UInt160 hash)
{
if (defs == null)
{
Expand All @@ -181,19 +182,12 @@ public bool IsContractCall(Mono.Cecil.MethodDefinition defs, out byte[] hash)
if (a.Type.FullName == "System.String")
{
string hashstr = (string)a.Value;

try
if (UInt160.TryParse(hashstr, out hash))
{
hash = hashstr.HexString2Bytes();
if (hash.Length != 20) throw new Exception("Wrong hash:" + hashstr);

hash = hash.Reverse().ToArray();
return true;
}
catch
{
throw new Exception("hex format error:" + hashstr);
}

throw new Exception("hex format error:" + hashstr);
}
else
{
Expand All @@ -202,12 +196,12 @@ public bool IsContractCall(Mono.Cecil.MethodDefinition defs, out byte[] hash)
{
throw new Exception("hash too short.");
}
hash = new byte[20];
var buffer = new byte[20];
for (var i = 0; i < 20; i++)
{
hash[i] = (byte)list[i].Value;
buffer[i] = (byte)list[i].Value;
}
hash = hash.Reverse().ToArray();
hash = new UInt160(buffer);
return true;
}
}
Expand Down Expand Up @@ -401,7 +395,7 @@ private int ConvertCall(OpCode src, NeoMethod to)
int calltype = 0;
string callname;
int callpcount = 0;
byte[] callhash = null;
UInt160 callhash = null;
VM.OpCode[] callcodes = null;
string[] calldata = null;

Expand Down Expand Up @@ -874,20 +868,28 @@ private int ConvertCall(OpCode src, NeoMethod to)
}
else if (calltype == 4)
{
// Package the arguments into an array.
ConvertPushNumber(pcount, null, to);
Convert1by1(VM.OpCode.PACK, null, to);
if (defs.IsGetter
&& defs.CustomAttributes.Any(a => a.AttributeType.FullName == "Neo.SmartContract.Framework.ContractHashAttribute"))
{
ConvertPushDataArray(callhash.ToArray(), src, to);
}
else
{
// Package the arguments into an array.
ConvertPushNumber(pcount, null, to);
Convert1by1(VM.OpCode.PACK, null, to);

// Push call method name, the first letter should be lowercase.
ConvertPushString(GetMethodName(defs.Body.Method), src, to);
// Push call method name, the first letter should be lowercase.
ConvertPushString(GetMethodName(defs.Body.Method), src, to);

// Push contract hash.
ConvertPushDataArray(callhash, src, to);
Insert1(VM.OpCode.SYSCALL, "", to, BitConverter.GetBytes(ApplicationEngine.System_Contract_Call));
// Push contract hash.
ConvertPushDataArray(callhash.ToArray(), src, to);
Insert1(VM.OpCode.SYSCALL, "", to, BitConverter.GetBytes(ApplicationEngine.System_Contract_Call));

// If the return type is void, insert a DROP.
if (defs.ReturnType.FullName is "System.Void")
Insert1(VM.OpCode.DROP, "", to);
// If the return type is void, insert a DROP.
if (defs.ReturnType.FullName is "System.Void")
Insert1(VM.OpCode.DROP, "", to);
}
}
else if (calltype == 5)
{
Expand Down Expand Up @@ -1451,6 +1453,7 @@ private int ConvertInitObj(OpCode src, NeoMethod to)
private int ConvertNewObj(ILMethod from, OpCode src, NeoMethod to)
{
var _type = (src.tokenUnknown as Mono.Cecil.MethodReference);

if (_type.FullName == "System.Void System.Numerics.BigInteger::.ctor(System.Byte[])")
{
return 0; // donothing;
Expand Down
4 changes: 2 additions & 2 deletions src/Neo.Compiler.MSIL/MSIL/Converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ public NeoModule Convert(ILModule _in, ConvOption option = null)
nm.paramtypes.Add(new NeoParam(src.name, src.type));
}

if (IsContractCall(m.Value.method, out byte[] outcall))
if (IsContractCall(m.Value.method, out _))
continue;
if (IsNonCall(m.Value.method))
continue;
if (IsMixAttribute(m.Value.method, out VM.OpCode[] opcodes, out string[] opdata))
if (IsMixAttribute(m.Value.method, out _, out _))
continue;

if (m.Key.Contains("::Main("))
Expand Down
10 changes: 9 additions & 1 deletion src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Neo.SmartContract.Framework\Neo.SmartContract.Framework.csproj" />
<ProjectReference Include="..\Neo.SmartContract.Framework\Neo.SmartContract.Framework.csproj">
<!--
The unified Neo domain model defines types with the same fully namespace qualified name
in different assemblies. Specifying a reference alias allows us to disambiguate types with
colliding names.
Official docs: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extern-alias
-->
<Aliases>scfx</Aliases>
</ProjectReference>
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions src/Neo.SmartContract.Framework/ContractHashAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace Neo.SmartContract.Framework
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
internal class ContractHashAttribute : Attribute
{

}
}
29 changes: 29 additions & 0 deletions src/Neo.SmartContract.Framework/ECPoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Neo.SmartContract.Framework;

namespace Neo.Cryptography.ECC
{
public class ECPoint
{
[OpCode(OpCode.CONVERT, StackItemType.ByteString)]
[OpCode(OpCode.DUP)]
[OpCode(OpCode.SIZE)]
[OpCode(OpCode.PUSHINT8, "21")] // 0x21 == 33 bytes expected array size
[OpCode(OpCode.NUMEQUAL)]
[OpCode(OpCode.ASSERT)]
public static extern explicit operator ECPoint(byte[] value);

[OpCode(OpCode.CONVERT, StackItemType.ByteString)]
[OpCode(OpCode.DUP)]
[OpCode(OpCode.SIZE)]
[OpCode(OpCode.PUSHINT8, "21")] // 0x21 == 33 bytes expected array size
[OpCode(OpCode.NUMEQUAL)]
[OpCode(OpCode.ASSERT)]
public static extern explicit operator ECPoint(ByteString value);

[Script]
public static extern implicit operator byte[](ECPoint value);

[Script]
public static extern implicit operator ByteString(ECPoint value);
}
}
2 changes: 1 addition & 1 deletion src/Neo.SmartContract.Framework/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public static byte ToByte(this int source)
/// Example: "AFsCjUGzicZmXQtWpwVt6hNeJTBwSipJMS".ToScriptHash() generates 0102030405060708090a0b0c0d0e0faabbccddee
/// </summary>
[NonemitWithConvert(ConvertMethod.ToScriptHash)]
public extern static byte[] ToScriptHash(this string address);
public extern static UInt160 ToScriptHash(this string address);

[NonemitWithConvert(ConvertMethod.ToBigInteger)]
public extern static BigInteger ToBigInteger(this string text);
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.SmartContract.Framework/Services/Neo/Account.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ namespace Neo.SmartContract.Framework.Services.Neo
public class Account
{
[Syscall("System.Contract.IsStandard")]
public static extern bool IsStandard(byte[] scripthash);
public static extern bool IsStandard(UInt160 scripthash);
}
}
8 changes: 4 additions & 4 deletions src/Neo.SmartContract.Framework/Services/Neo/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ namespace Neo.SmartContract.Framework.Services.Neo
{
public class Block
{
public readonly byte[] Hash;
public readonly UInt256 Hash;
public readonly uint Version;
public readonly byte[] PrevHash;
public readonly byte[] MerkleRoot;
public readonly UInt256 PrevHash;
public readonly UInt256 MerkleRoot;
public readonly ulong Timestamp;
public readonly uint Index;
public readonly byte[] NextConsensus;
public readonly UInt160 NextConsensus;
public readonly int TransactionsCount;
}
}
10 changes: 5 additions & 5 deletions src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ public static class Blockchain
public static extern Block GetBlock(uint height);

[Syscall("System.Blockchain.GetBlock")]
public static extern Block GetBlock(byte[] hash);
public static extern Block GetBlock(UInt256 hash);

[Syscall("System.Blockchain.GetTransaction")]
public static extern Transaction GetTransaction(byte[] hash);
public static extern Transaction GetTransaction(UInt256 hash);

[Syscall("System.Blockchain.GetTransactionFromBlock")]
public static extern Transaction GetTransactionFromBlock(byte[] blockHash, int txIndex);
public static extern Transaction GetTransactionFromBlock(UInt256 blockHash, int txIndex);

[Syscall("System.Blockchain.GetTransactionFromBlock")]
public static extern Transaction GetTransactionFromBlock(uint blockIndex, int txIndex);

[Syscall("System.Blockchain.GetTransactionHeight")]
public static extern BigInteger GetTransactionHeight(byte[] hash);
public static extern BigInteger GetTransactionHeight(UInt256 hash);

[Syscall("System.Blockchain.GetContract")]
public static extern Contract GetContract(byte[] script_hash);
public static extern Contract GetContract(UInt160 script_hash);
}
}
6 changes: 3 additions & 3 deletions src/Neo.SmartContract.Framework/Services/Neo/Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ public class Contract
public readonly bool IsPayable;

[Syscall("System.Contract.Call")]
public static extern object Call(byte[] scriptHash, string method, object[] arguments);
public static extern object Call(UInt160 scriptHash, string method, object[] arguments);

[Syscall("System.Contract.CallEx")]
public static extern object CallEx(byte[] scriptHash, string method, object[] arguments, CallFlags flag);
public static extern object CallEx(UInt160 scriptHash, string method, object[] arguments, CallFlags flag);

[Syscall("System.Contract.Create")]
public static extern Contract Create(byte[] script, string manifest);
Expand All @@ -41,6 +41,6 @@ public class Contract
public static extern byte GetCallFlags();

[Syscall("System.Contract.CreateStandardAccount")]
public static extern byte[] CreateStandardAccount(byte[] pubKey);
public static extern UInt160 CreateStandardAccount(Cryptography.ECC.ECPoint pubKey);
}
}
8 changes: 4 additions & 4 deletions src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ public static class ECDsa
public static class Secp256r1
{
[Syscall("Neo.Crypto.VerifyWithECDsaSecp256r1")]
public extern static bool Verify(byte[] message, byte[] pubkey, byte[] signature);
public extern static bool Verify(byte[] message, Cryptography.ECC.ECPoint pubkey, byte[] signature);

[Syscall("Neo.Crypto.CheckMultisigWithECDsaSecp256r1")]
public extern static bool CheckMultiSig(byte[] message, byte[][] pubkey, byte[][] signature);
public extern static bool CheckMultiSig(byte[] message, Cryptography.ECC.ECPoint[] pubkey, byte[][] signature);
}

public static class Secp256k1
{
[Syscall("Neo.Crypto.VerifyWithECDsaSecp256k1")]
public extern static bool Verify(byte[] message, byte[] pubkey, byte[] signature);
public extern static bool Verify(byte[] message, Cryptography.ECC.ECPoint pubkey, byte[] signature);

[Syscall("Neo.Crypto.CheckMultisigWithECDsaSecp256k1")]
public extern static bool CheckMultiSig(byte[] message, byte[][] pubkey, byte[][] signature);
public extern static bool CheckMultiSig(byte[] message, Cryptography.ECC.ECPoint[] pubkey, byte[][] signature);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Neo.SmartContract.Framework/Services/Neo/Designation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace Neo.SmartContract.Framework.Services.Neo
[Contract("0x763afecf3ebba0a67568a2c8be06e8f068c62666")]
public class Designation
{
public static extern UInt160 Hash { [ContractHash] get; }
public static extern string Name { get; }
public static extern byte[][] GetDesignatedByRole(DesignationRole role);
public static extern Cryptography.ECC.ECPoint[] GetDesignatedByRole(DesignationRole role);
}
}
5 changes: 3 additions & 2 deletions src/Neo.SmartContract.Framework/Services/Neo/GAS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ namespace Neo.SmartContract.Framework.Services.Neo
[Contract("0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc")]
public class GAS
{
public static extern UInt160 Hash { [ContractHash] get; }
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);
public static extern bool Transfer(byte[] from, byte[] to, BigInteger amount);
public static extern BigInteger BalanceOf(UInt160 account);
public static extern bool Transfer(UInt160 from, UInt160 to, BigInteger amount);
}
}
Loading