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

Feature manifest and permission system #766

Merged
merged 66 commits into from
May 24, 2019
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
9e101ab
Classes
shargon May 20, 2019
0ab7368
Check Valid group signature
shargon May 20, 2019
f548702
Is Allowed
shargon May 20, 2019
143297b
Reuse some classes
shargon May 20, 2019
dfed28b
Fix IsAllowed
shargon May 20, 2019
5ce76cc
Trusts and SafeMethods
shargon May 20, 2019
6b26077
Process trust and Group
shargon May 20, 2019
8781770
Clean code
shargon May 20, 2019
a1c6f72
Add comments
shargon May 20, 2019
5b1aaec
Add more comments
shargon May 20, 2019
34aa3ba
WillCardContainer
shargon May 21, 2019
ed75324
Group as Array
shargon May 21, 2019
f7f36e8
Willcard in ContractPermission
shargon May 21, 2019
2058fd0
Fix trusts
shargon May 21, 2019
deb3707
Clean code
shargon May 21, 2019
6d1d627
Merge branch 'master' into feature-manifest
shargon May 21, 2019
44f5ce0
Merge branch 'master' into feature-manifest
shargon May 21, 2019
1f8b316
Typo fix
shargon May 21, 2019
0137897
Integrate ContractManifest
shargon May 21, 2019
7736247
Integrate in Contract.Call
shargon May 21, 2019
3a5b0ba
Clone Manifest
shargon May 21, 2019
453675c
full manifest in json
shargon May 21, 2019
55fd385
Default value in constructor
shargon May 21, 2019
cd306e8
Serialize ContractManifest
shargon May 21, 2019
2b40a8d
Default Abi for Native Contract
shargon May 21, 2019
6b36687
Fix return for PolicyContract
shargon May 21, 2019
c402d0b
Nep5Token Abi
shargon May 21, 2019
f33b0e8
Clean code
shargon May 21, 2019
ce0aa85
Abi for GastToken
shargon May 21, 2019
89051bf
Abi for NeoToken
shargon May 21, 2019
93d6ae8
Default entry point in the static method
shargon May 21, 2019
768df1f
MaxLength for ContractManifest
shargon May 21, 2019
0729674
Migrate too
shargon May 21, 2019
7842694
Merge branch 'master' into feature-manifest
shargon May 22, 2019
524a745
Parsing json
shargon May 22, 2019
548acf0
Merge remote-tracking branch 'shargon/feature-manifest' into feature-…
shargon May 22, 2019
16d1ff5
Unit test for json
shargon May 22, 2019
c09a795
Validate ContractManifest
shargon May 22, 2019
47b3efc
Neo.Contract.UpdateManifest
shargon May 22, 2019
1cb3650
Deserialize
shargon May 22, 2019
2b9c5dc
Check hash of the manifest in update
shargon May 22, 2019
c18cd5b
Rename classes
shargon May 22, 2019
31feebc
Erik recommendations
shargon May 23, 2019
3f0772b
Move default entry point
shargon May 23, 2019
ecb338f
Revert Helper.cs
erikzhang May 23, 2019
f94021b
fix tests
erikzhang May 23, 2019
1d4e281
Change the type of `ContractManifestGroup.PubKey` to `ECPoint`
erikzhang May 23, 2019
6bc60f1
Move classes to namespace `Neo.SmartContract.Manifest`, and rename
erikzhang May 23, 2019
8d38246
Remove `Equals()`
erikzhang May 23, 2019
93cd013
Fix `DefaultEntryPoint`
erikzhang May 23, 2019
4dacb2c
Fix `ToJson()` and `ContractManifest.CreateDefault()`
erikzhang May 23, 2019
5400351
Add `ContractManifest.DeserializeFromJson()`
erikzhang May 23, 2019
cc4a340
optimize
erikzhang May 23, 2019
dab02a5
Groups never be null
shargon May 23, 2019
38fc8d7
Not allowed to be set to null
erikzhang May 23, 2019
26ff492
Combine `Neo.Contract.Migrate` and `Neo.Contract.UpdateManifest`
erikzhang May 23, 2019
d00903e
Ensure `contract.Manifest.Hash == contract.ScriptHash` in `Contract_C…
erikzhang May 23, 2019
12a1576
rename
erikzhang May 23, 2019
162758e
Fix `Contract_Call`
erikzhang May 23, 2019
2cdb847
Implement `ContractPermission` correctly
erikzhang May 23, 2019
84c38f9
Simplify `IsValid()`
erikzhang May 23, 2019
fcdab61
Update ContractGroup.cs
shargon May 23, 2019
7c7a82d
Change max length of ContractManifest
shargon May 23, 2019
efac87f
Add `events` for ABI of `Nep5Token`
erikzhang May 23, 2019
a3a1b0d
format
erikzhang May 23, 2019
b44ec29
Update WildCardContainer.cs
erikzhang May 23, 2019
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
28 changes: 28 additions & 0 deletions neo/SmartContract/ContractAbi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Neo.SmartContract
{
/// <summary>
/// For technical details of ABI, please refer to NEP-3: NeoContract ABI. (https://github.com/neo-project/proposals/blob/master/nep-3.mediawiki)
/// </summary>
public class ContractAbi
{
/// <summary>
/// Hash is the script hash of the contract. It is encoded as a hexadecimal string in big-endian.
/// </summary>
public UInt160 Hash { get; set; }

/// <summary>
/// Entrypoint is a Method object which describe the details of the entrypoint of the contract.
/// </summary>
public ContractMethodWithReturnDefinition EntryPoint { get; set; }

/// <summary>
/// Methods is an array of Method objects which describe the details of each method in the contract.
/// </summary>
public ContractMethodWithReturnDefinition[] Methods { get; set; }

/// <summary>
/// Events is an array of Event objects which describe the details of each event in the contract.
/// </summary>
public ContractMethodDefinition[] Events { get; set; }
}
}
77 changes: 77 additions & 0 deletions neo/SmartContract/ContractManifest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Neo.Ledger;
using System;
using System.Linq;

namespace Neo.SmartContract
{
/// <summary>
/// When a smart contract is deployed, it must explicitly declare the features and permissions it will use.
/// When it is running, it will be limited by its declared list of features and permissions, and cannot make any behavior beyond the scope of the list.
/// </summary>
public class ContractManifest
{
/// <summary>
/// Contract hash
/// </summary>
public UInt160 Hash { get; set; }
erikzhang marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// A group represents a set of mutually trusted contracts. A contract will trust and allow any contract in the same group to invoke it, and the user interface will not give any warnings.
/// The group field can be null.
/// </summary>
public ContractManifestGroup[] Groups { get; set; }

/// <summary>
/// The features field describes what features are available for the contract.
/// </summary>
public ContractPropertyState Features { get; set; }

/// <summary>
/// For technical details of ABI, please refer to NEP-3: NeoContract ABI. (https://github.com/neo-project/proposals/blob/master/nep-3.mediawiki)
/// </summary>
public ContractAbi Abi { get; set; }

/// <summary>
/// The permissions field is an array containing a set of Permission objects. It describes which contracts may be invoked and which methods are called.
/// </summary>
public WillCardContainer<ContractPermission> Permissions { get; set; }

/// <summary>
/// The trusts field is an array containing a set of contract hashes or group public keys. It can also be assigned with a wildcard *. If it is a wildcard *, then it means that it trusts any contract.
/// If a contract is trusted, the user interface will not give any warnings when called by the contract.
/// </summary>
public WillCardContainer<UInt160> Trusts { get; set; }

/// <summary>
/// The safemethods field is an array containing a set of method names. It can also be assigned with a wildcard *. If it is a wildcard *, then it means that all methods of the contract are safe.
/// If a method is marked as safe, the user interface will not give any warnings when it is called by any other contract.
/// </summary>
public WillCardContainer<string> SafeMethods { get; set; }

/// <summary>
/// Return true if is allowed
/// </summary>
/// <param name="manifest">Manifest</param>
/// <param name="method">Method</param>
/// <returns>Return true or false</returns>
public bool CanCall(ContractManifest manifest, string method)
{
if (Groups != null && manifest.Groups != null && Groups.Any(a => manifest.Groups.Any(b => a.PubKey.Equals(b.PubKey))))
{
// Same group

return true;
}

if (manifest.Trusts != null && !manifest.Trusts.IsWildcard && !manifest.Trusts.Contains(Hash))
{
// null == * wildcard
// You don't have rights in the contract

return false;
}

return Permissions == null || Permissions.IsWildcard || Permissions.Any(u => u.IsAllowed(manifest.Hash, method));
}
}
}
32 changes: 32 additions & 0 deletions neo/SmartContract/ContractManifestGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Neo.Cryptography;

namespace Neo.SmartContract
{
/// <summary>
/// A group represents a set of mutually trusted contracts. A contract will trust and allow any contract in the same group to invoke it, and the user interface will not give any warnings.
/// The group field can be null.
/// A group is identified by a public key and must be accompanied by a signature for the contract hash to prove that the contract is indeed included in the group.
/// </summary>
public class ContractManifestGroup
{
/// <summary>
/// Pubkey represents the public key of the group.
/// </summary>
public UInt160 PubKey { get; set; }

/// <summary>
/// Signature is the signature of the contract hash.
/// </summary>
public byte[] Signature { get; set; }

/// <summary>
/// Return true if the signature is valid
/// </summary>
/// <param name="contractHash">Contract Hash</param>
/// <returns>Return true or false</returns>
public bool IsValid(UInt160 contractHash)
{
return Crypto.Default.VerifySignature(contractHash.ToArray(), Signature, PubKey.ToArray());
}
}
}
15 changes: 15 additions & 0 deletions neo/SmartContract/ContractMethodDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Neo.SmartContract
{
public class ContractMethodDefinition
{
/// <summary>
/// Name is the name of the method, which can be any valid identifier.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Parameters is an array of Parameter objects which describe the details of each parameter in the method.
/// </summary>
public ContractParameterDefinition[] Parameters { get; set; }
}
}
11 changes: 11 additions & 0 deletions neo/SmartContract/ContractMethodWithReturnDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Neo.SmartContract
{
public class ContractMethodWithReturnDefinition : ContractMethodDefinition
{
/// <summary>
/// Returntype indicates the return type of the method. It can be one of the following values:
/// Signature, Boolean, Integer, Hash160, Hash256, ByteArray, PublicKey, String, Array, InteropInterface, Void.
/// </summary>
public ContractParameterType ReturnType { get; set; }
}
}
16 changes: 16 additions & 0 deletions neo/SmartContract/ContractParameterDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Neo.SmartContract
{
public class ContractParameterDefinition
{
/// <summary>
/// Name is the name of the parameter, which can be any valid identifier.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Type indicates the type of the parameter. It can be one of the following values:
/// Signature, Boolean, Integer, Hash160, Hash256, ByteArray, PublicKey, String, Array, InteropInterface.
/// </summary>
public ContractParameterType Type { get; set; }
}
}
41 changes: 41 additions & 0 deletions neo/SmartContract/ContractPermission.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Linq;

namespace Neo.SmartContract
{
/// <summary>
/// The permissions field is an array containing a set of Permission objects. It describes which contracts may be invoked and which methods are called.
/// </summary>
public class ContractPermission
{
/// <summary>
/// The contract field indicates the contract to be invoked. It can be a hash of a contract, a public key of a group, or a wildcard *.
/// If it specifies a hash of a contract, then the contract will be invoked; If it specifies a public key of a group, then any contract in this group will be invoked; If it specifies a wildcard*, then any contract will be invoked.
/// </summary>
public UInt160 Contract { get; set; }

/// <summary>
/// The methods field is an array containing a set of methods to be called. It can also be assigned with a wildcard *. If it is a wildcard *, then it means that any method can be called.
/// If a contract invokes a contract or method that is not declared in the manifest at runtime, the invocation will fail.
/// </summary>
public WillCardContainer<string> Methods { get; set; }

/// <summary>
/// Return true if is allowed
/// </summary>
/// <param name="contractHash">Contract hash</param>
/// <param name="method">Method</param>
/// <returns>Return true or false</returns>
public bool IsAllowed(UInt160 contractHash, string method)
{
if (!Contract.Equals(contractHash))
{
// 0x00 = * wildcard

if (Contract != UInt160.Zero) return false;
}

return Methods == null || Methods.IsWildcard || Methods.Contains(method);
}
}
}
48 changes: 48 additions & 0 deletions neo/SmartContract/WillCardContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;

namespace Neo.SmartContract
{
public class WillCardContainer<T> : IReadOnlyList<T>
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly T[] _data;

public T this[int index] => _data[index];

/// <summary>
/// Number of items
/// </summary>
public int Count => _data?.Length ?? 0;

/// <summary>
/// Is will card?
/// </summary>
public bool IsWildcard => _data == null;

/// <summary>
/// Constructor
/// </summary>
/// <param name="data">Data</param>
public WillCardContainer(T[] data)
{
_data = data;
}

/// <summary>
/// Create a new WillCardContainer
/// </summary>
/// <param name="data">Data</param>
/// <returns>WillCardContainer</returns>
public static WillCardContainer<T> Create(params T[] data) => new WillCardContainer<T>(data);

/// <summary>
/// Create a will card
/// </summary>
/// <returns>WillCardContainer</returns>
public static WillCardContainer<T> CreateWildcard() => new WillCardContainer<T>(null);

public IEnumerator<T> GetEnumerator() => ((IReadOnlyList<T>)_data).GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}