From 5321e26cd1d3a002b30f8c916663316a74137530 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 23 May 2024 18:12:43 +0200 Subject: [PATCH] draft --- .../Manifest/ContractMethodDescriptor.cs | 28 +++++- .../Manifest/ContractParameterDefinition.cs | 36 +++++++- .../SmartContract/Manifest/ExtendedType.cs | 89 +++++++++++++++++++ 3 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 src/Neo/SmartContract/Manifest/ExtendedType.cs diff --git a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs index cc8d0a16d5..93a2d92dbc 100644 --- a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs @@ -27,6 +27,11 @@ public class ContractMethodDescriptor : ContractEventDescriptor /// public ContractParameterType ReturnType { get; set; } + /// + /// NEP-25 extended return type + /// + public ExtendedType? ExtendedReturnType { get; set; } + /// /// The position of the method in the contract script. /// @@ -45,14 +50,28 @@ public override void FromStackItem(StackItem stackItem) ReturnType = (ContractParameterType)(byte)@struct[2].GetInteger(); Offset = (int)@struct[3].GetInteger(); Safe = @struct[4].GetBoolean(); + if (@struct.Count >= 6) + { + ExtendedReturnType = new ExtendedType(); + ExtendedReturnType.FromStackItem((VM.Types.Array)@struct[5], 0); + } + else + { + ExtendedReturnType = null; + } } public override StackItem ToStackItem(ReferenceCounter referenceCounter) { - Struct @struct = (Struct)base.ToStackItem(referenceCounter); + var @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add((byte)ReturnType); @struct.Add(Offset); @struct.Add(Safe); + if (ExtendedReturnType != null) + { + var structExtended = new Struct(referenceCounter); + @struct.Add(ExtendedReturnType.ToStackItem(referenceCounter, structExtended)); + } return @struct; } @@ -69,7 +88,8 @@ public override StackItem ToStackItem(ReferenceCounter referenceCounter) Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), ReturnType = Enum.Parse(json["returntype"].GetString()), Offset = json["offset"].GetInt32(), - Safe = json["safe"].GetBoolean() + Safe = json["safe"].GetBoolean(), + ExtendedReturnType = json["extendedreturntype"] != null ? ExtendedType.FromJson((JObject)json["extendedreturntype"]) : null }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); @@ -88,6 +108,10 @@ public override JObject ToJson() json["returntype"] = ReturnType.ToString(); json["offset"] = Offset; json["safe"] = Safe; + if (ExtendedReturnType != null) + { + json["extendedreturntype"] = ExtendedReturnType.ToString(); + } return json; } } diff --git a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs index 61906558d0..f989afab58 100644 --- a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs +++ b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs @@ -31,16 +31,39 @@ public class ContractParameterDefinition : IInteroperable /// public ContractParameterType Type { get; set; } + /// + /// NEP-25 extended type + /// + public ExtendedType? ExtendedType { get; set; } + void IInteroperable.FromStackItem(StackItem stackItem) { - Struct @struct = (Struct)stackItem; + var @struct = (Struct)stackItem; Name = @struct[0].GetString(); Type = (ContractParameterType)(byte)@struct[1].GetInteger(); + + if (@struct.Count >= 3) + { + ExtendedType = new ExtendedType(); + ExtendedType.FromStackItem((VM.Types.Array)@struct[5], 0); + } + else + { + ExtendedType = null; + } } public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Struct(referenceCounter) { Name, (byte)Type }; + var @struct = new Struct(referenceCounter) { Name, (byte)Type }; + + if (ExtendedType != null) + { + var structExtended = new Struct(referenceCounter); + @struct.Add(ExtendedType.ToStackItem(referenceCounter, structExtended)); + } + + return @struct; } /// @@ -50,10 +73,11 @@ public StackItem ToStackItem(ReferenceCounter referenceCounter) /// The converted parameter. public static ContractParameterDefinition FromJson(JObject json) { - ContractParameterDefinition parameter = new() + var parameter = new ContractParameterDefinition() { Name = json["name"].GetString(), - Type = Enum.Parse(json["type"].GetString()) + Type = Enum.Parse(json["type"].GetString()), + ExtendedType = json["extendedtype"] != null ? ExtendedType.FromJson((JObject)json["extendedtype"]) : null, }; if (string.IsNullOrEmpty(parameter.Name)) throw new FormatException(); @@ -71,6 +95,10 @@ public JObject ToJson() var json = new JObject(); json["name"] = Name; json["type"] = Type.ToString(); + if (ExtendedType != null) + { + json["extendedtype"] = ExtendedType.ToString(); + } return json; } } diff --git a/src/Neo/SmartContract/Manifest/ExtendedType.cs b/src/Neo/SmartContract/Manifest/ExtendedType.cs new file mode 100644 index 0000000000..c1b0d89ac7 --- /dev/null +++ b/src/Neo/SmartContract/Manifest/ExtendedType.cs @@ -0,0 +1,89 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// ExtendedType.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Json; +using Neo.VM; +using Neo.VM.Types; +using System; + +namespace Neo.SmartContract.Manifest +{ + public class ExtendedType : IInteroperable + { + /// + /// The type of the parameter. It can be any value of except . + /// + public ContractParameterType Type { get; set; } + + /// + /// NamedType is used to refer to one of the types defined in the namedtypes object of Contract, + /// so namedtypes MUST contain a field named name. + /// This field is only used for structures (ordered set of named values of diffent types), + /// if used other fields MUST NOT be set, except for the type which MUST be an Array. + /// Value string MUST start with a letter and can contain alphanumeric characters and dots. + /// It MUST NOT be longer than 64 characters. + /// + public string NamedType { get; set; } + + void IInteroperable.FromStackItem(StackItem stackItem) + { + FromStackItem((VM.Types.Array)stackItem, 0); + } + + internal void FromStackItem(VM.Types.Array @struct, int startIndex) + { + Type = (ContractParameterType)(byte)@struct[startIndex].GetInteger(); + NamedType = @struct[startIndex + 1].GetString(); + } + + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + { + Struct @struct = new Struct(referenceCounter); + ToStackItem(referenceCounter, @struct); + return @struct; + } + + internal StackItem ToStackItem(ReferenceCounter referenceCounter, Struct @struct) + { + @struct.Add((byte)Type); + @struct.Add(NamedType); + return @struct; + } + + /// + /// Converts the type from a JSON object. + /// + /// The method represented by a JSON object. + /// The extended type. + public static ExtendedType FromJson(JObject json) + { + ExtendedType type = new() + { + Type = Enum.Parse(json["type"].GetString()), + NamedType = json["namedtype"].GetString(), + }; + if (!Enum.IsDefined(typeof(ContractParameterType), type.Type)) throw new FormatException(); + return type; + } + + /// + /// Converts the parameter to a JSON object. + /// + /// The parameter represented by a JSON object. + public virtual JObject ToJson() + { + var json = new JObject(); + json["type"] = Type.ToString(); + json["namedtype"] = NamedType; + return json; + } + } +}