From eef2df5ad5faa58c47170317ffa5a4e30ea73eec Mon Sep 17 00:00:00 2001 From: Umut Onat Artuvan Date: Fri, 26 Jun 2020 21:10:40 +0200 Subject: [PATCH] first working version --- SCTransformation.API/Startup.cs | 4 - .../ClientApplicationGenerator.cs | 52 ++++----- SCTransformation/Models/JavaScript.cs | 3 +- SCTransformation/Models/Solidity.cs | 3 + .../SmartContractDescriptorGenerator.cs | 110 ++++++++++-------- .../smartcontract/ControllerEvents.st | 20 ++-- .../Visitors/JavaScriptVisitor.cs | 46 +++++--- SCTransformation/Visitors/SolidityVisitor.cs | 20 +++- 8 files changed, 143 insertions(+), 115 deletions(-) diff --git a/SCTransformation.API/Startup.cs b/SCTransformation.API/Startup.cs index 406fe4d..96d6c03 100644 --- a/SCTransformation.API/Startup.cs +++ b/SCTransformation.API/Startup.cs @@ -18,8 +18,6 @@ public Startup(IConfiguration configuration) } public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); @@ -31,8 +29,6 @@ public void ConfigureServices(IServiceCollection services) c.IncludeXmlComments(xmlPath); }); } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) diff --git a/SCTransformation/ClientApplicationGenerator.cs b/SCTransformation/ClientApplicationGenerator.cs index 876affd..f04220c 100644 --- a/SCTransformation/ClientApplicationGenerator.cs +++ b/SCTransformation/ClientApplicationGenerator.cs @@ -20,9 +20,9 @@ public static void Main(string[] args) { var scds = SmartContractDescriptorGenerator.Transform( File.ReadAllText( - "/Users/artuvan/Github/SmartContractDescriptorsGenerator/SCTransformation/Resources/in.sol"), - "Solidity"); - BuildJavaApplication(scds.First(), "com.danyue", "call"); + "/Users/artuvan/Github/SmartContractDescriptorsGenerator/SCTransformation/Resources/in.js"), + "JavaScript"); + BuildJavaApplication(scds.First(), "com.uni.stuttgart", "callback"); } private static string BuildJavaApplication(SmartContractDescriptor smartContractDescriptor, @@ -45,15 +45,11 @@ private static string BuildJavaApplication(SmartContractDescriptor smartContract var smartContractPath = path.Replace("smartcontract", smartContractDescriptor.Name.ToLower()); foreach (var function in smartContractDescriptor.Functions) { - var tempPath = smartContractPath.Replace("Function", - System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase( - function.Name.ToLower())); + var tempPath = smartContractPath.Replace("Function", ToUpperFirstLetter(function.Name)); var functionTemplate = CreateFreshTemplate(stream, smartContractDescriptor, packageName, callbackUrl); - functionTemplate.Add("functionParameterName", - System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase( - function.Name.ToLower())); + functionTemplate.Add("functionParameterName", ToUpperFirstLetter(function.Name)); foreach (var parameter in function.Inputs) { functionTemplate.Add("parameterarray", @@ -81,24 +77,18 @@ private static string BuildJavaApplication(SmartContractDescriptor smartContract { var template = CreateFreshTemplate(stream, smartContractDescriptor, packageName, callbackUrl); - template.Add("functionParameter", - System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase( - function.Name.ToLower())); + template.Add("functionParameter", ToUpperFirstLetter(function.Name)); var privateFunction = new Function { Name = function.Name, - FirstCapital = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo - .ToTitleCase( - function.Name.ToLower()) + FirstCapital = ToUpperFirstLetter(function.Name) }; template.Add("functionArray", new[] {privateFunction}); foreach (var parameter in function.Inputs) { var privateParameter = new Parameter { - FirstCapital = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo - .ToTitleCase( - parameter.Name.ToLower()), + FirstCapital = ToUpperFirstLetter(parameter.Name), Name = parameter.Name, ParamType = parameter.Type }; @@ -126,18 +116,14 @@ private static string BuildJavaApplication(SmartContractDescriptor smartContract var privateEvent= new Event { Name = scEvent.Name, - FirstCapital = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo - .ToTitleCase( - scEvent.Name.ToLower()) + FirstCapital = ToUpperFirstLetter(scEvent.Name) }; template.Add("eventArray", new[] {privateEvent}); foreach (var parameter in scEvent.Outputs) { var privateParameter = new Parameter { - FirstCapital = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo - .ToTitleCase( - parameter.Name.ToLower()), + FirstCapital = ToUpperFirstLetter(parameter.Name), Name = parameter.Name, ParamType = parameter.Type }; @@ -162,8 +148,7 @@ private static string BuildJavaApplication(SmartContractDescriptor smartContract { var smartContractPath = path.Replace("smartcontract", smartContractDescriptor.Name.ToLower()); smartContractPath = smartContractPath.Replace("SmartContract", - System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase( - smartContractDescriptor.Name.ToLower())); + ToUpperFirstLetter(smartContractDescriptor.Name)); files.Add(new KeyValuePair(CreateDirectory(smartContractPath, packageName), Regex.Escape( $"{controllerHeader}{controllerFunctions}{controllerEvents}{controllerFooter}"))); @@ -189,9 +174,7 @@ private static Template CreateFreshTemplate(Stream stream, SmartContractDescript template.Add("sclAddress", smartContractDescriptor.SclAddress); template.Add("callbackUrl", callbackUrl); template.Add("contractPackageName", smartContractDescriptor.Name.ToLower()); - template.Add("contractName", - System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase( - smartContractDescriptor.Name.ToLower())); + template.Add("contractName", ToUpperFirstLetter(smartContractDescriptor.Name)); return template; } @@ -272,5 +255,16 @@ private class Event public string Name; public string FirstCapital; } + + private static string ToUpperFirstLetter(string source) + { + if (string.IsNullOrEmpty(source)) + { + return string.Empty; + } + var letters = source.ToCharArray(); + letters[0] = char.ToUpper(letters[0]); + return new string(letters); + } } } \ No newline at end of file diff --git a/SCTransformation/Models/JavaScript.cs b/SCTransformation/Models/JavaScript.cs index 9089538..670e3d3 100644 --- a/SCTransformation/Models/JavaScript.cs +++ b/SCTransformation/Models/JavaScript.cs @@ -35,9 +35,10 @@ public class Variable public class Function { public string Name { get; set; } - public string EventName { get; set; } + public List Events { get; set; } public List Inputs { get; set; } public List Outputs { get; set; } + public bool HasSideEffects { get; set; } } } } \ No newline at end of file diff --git a/SCTransformation/Models/Solidity.cs b/SCTransformation/Models/Solidity.cs index dd5e1d4..50369fe 100644 --- a/SCTransformation/Models/Solidity.cs +++ b/SCTransformation/Models/Solidity.cs @@ -9,6 +9,7 @@ public class Solidity public List Imports { get; set; } public List Contracts { get; set; } public BlockChainType BlockChainType { get; set; } + public class Contract { public bool IsStateful { get; set; } @@ -35,7 +36,9 @@ public class Function public List Parameters { get; set; } public List ReturnParameters { get; set; } public ModifierList ModifierList { get; set; } + public List Events { get; set; } public Scope Scope { get; set; } + public bool HasSideEffects { get; set; } } public class Event diff --git a/SCTransformation/SmartContractDescriptorGenerator.cs b/SCTransformation/SmartContractDescriptorGenerator.cs index 5bbd391..8d3aee2 100644 --- a/SCTransformation/SmartContractDescriptorGenerator.cs +++ b/SCTransformation/SmartContractDescriptorGenerator.cs @@ -111,6 +111,7 @@ private static IEnumerable SolidityToScd(Solidity solid { var inputs = new List(); var outputs = new List(); + var functionEvents= new List(); foreach (var input in function.Parameters) { inputs.Add(new SmartContractDescriptor.Parameter @@ -131,13 +132,18 @@ private static IEnumerable SolidityToScd(Solidity solid }); } + foreach (var functionEvent in function.Events) + { + functionEvents.Add(functionEvent); + } + functions.Add(new SmartContractDescriptor.Function { Name = function.Name, Description = string.Empty, - Dispatcher = string.Empty, //TODO: - Events = new List(), //TODO: - HasSideEffects = false, //TODO: + Dispatcher = string.Empty, + Events = functionEvents, + HasSideEffects = function.HasSideEffects, Inputs = inputs, Outputs = outputs, Scope = function.Scope @@ -202,62 +208,66 @@ private static IEnumerable JavaScriptToScd(JavaScript j methods.AddRange(javaScript.Functions); foreach (var function in methods) { - if (function.EventName != null) + var inputs = new List(); + var outputs = new List(); + var functionEvents = new List(); + foreach (var input in function.Inputs) { - var inputs = new List(); - var outputs = new List(); - foreach (var input in function.Inputs) - { - inputs.Add(new SmartContractDescriptor.Parameter - { - Name = input.Name, - Type = input.Type, - IsIndexed = false - }); - } - - foreach (var output in function.Outputs) + inputs.Add(new SmartContractDescriptor.Parameter { - outputs.Add(new SmartContractDescriptor.Parameter - { - Name = output.Name, - Type = output.Type, - IsIndexed = false - }); - } + Name = input.Name, + Type = input.Type, + IsIndexed = false + }); + } - functions.Add(new SmartContractDescriptor.Function + foreach (var output in function.Outputs) + { + outputs.Add(new SmartContractDescriptor.Parameter { - Name = function.Name, - Description = string.Empty, - Dispatcher = "", //TODO: - Events = new List(), //TODO: - HasSideEffects = false, //TODO: - Inputs = inputs, - Outputs = outputs, - Scope = Scope.Public + Name = output.Name, + Type = output.Type, + IsIndexed = false }); } - else + + if (function.Events.Count > 0) { - var outputs = new List(); - foreach (var output in function.Outputs) + foreach (var functionEvent in function.Events) { - outputs.Add(new SmartContractDescriptor.Parameter + var eventOutputs = new List(); + foreach (var output in function.Outputs) { - Name = output.Name, - Type = output.Type, - IsIndexed = false + eventOutputs.Add(new SmartContractDescriptor.Parameter + { + Name = output.Name, + Type = output.Type, + IsIndexed = false + }); + } + + functionEvents.Add(functionEvent); + + events.Add(new SmartContractDescriptor.Event + { + Name = functionEvent, + Description = string.Empty, + Outputs = eventOutputs }); } - - events.Add(new SmartContractDescriptor.Event - { - Name = function.Name, - Description = string.Empty, - Outputs = outputs - }); } + + functions.Add(new SmartContractDescriptor.Function + { + Name = function.Name, + Description = string.Empty, + Dispatcher = string.Empty, + Events = functionEvents, + HasSideEffects = function.HasSideEffects, + Inputs = inputs, + Outputs = outputs, + Scope = Scope.Public + }); } var scdList = new List @@ -322,9 +332,9 @@ private static IEnumerable GoToScd(Go go) { Name = function.Name, Description = string.Empty, - Dispatcher = "", //TODO: - Events = new List(), //TODO: - HasSideEffects = false, //TODO: + Dispatcher = string.Empty, + Events = new List(), + HasSideEffects = false, Inputs = inputs, Outputs = outputs, Scope = Scope.Public diff --git a/SCTransformation/Templates/JavaApplication/controller/smartcontract/ControllerEvents.st b/SCTransformation/Templates/JavaApplication/controller/smartcontract/ControllerEvents.st index 2d6f7a4..86961ac 100644 --- a/SCTransformation/Templates/JavaApplication/controller/smartcontract/ControllerEvents.st +++ b/SCTransformation/Templates/JavaApplication/controller/smartcontract/ControllerEvents.st @@ -1,28 +1,28 @@ -€eventArray:{eventName| +€eventArray:{event| @CrossOrigin - @RequestMapping(value = "/query/€eventName€", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE\}) + @RequestMapping(value = "/query/€event.Name€", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE\}) public List query€event.FirstCapital€(@RequestBody QueryInput input) { List parameters= new ArrayList(){ - €eventoutputparameterarray:{it|{add(new Parameter().builder().name("€it.name€").type("{\"type\": \"€it.type€\"\}").build());\}};separator="\n"€ + €eventoutputparameterarray:{it|{add(new Parameter().builder().name("€it.Name€").type("{\"type\": \"€it.Type€\"\}").build());\}};separator="\n"€ \}; - return scipClientFunctions.performQuery(null,"€eventName€",parameters,input.getFilter(),input.getTimeFrame()); + return scipClientFunctions.performQuery(null,"€event.Name€",parameters,input.getFilter(),input.getTimeFrame()); \} @CrossOrigin - @RequestMapping(value = "/subscribe/€eventName€", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE\}) + @RequestMapping(value = "/subscribe/€event.Name€", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE\}) public Observable subscribe€event.FirstCapital€(@RequestBody SubscribeInput input) { List parameters= new ArrayList(){ - €eventoutputparameterarray:{it|{add(new Parameter().builder().name("€it.name€").type("{\"type\": \"€it.type€\"\}").build());\}};separator="\n"€ + €eventoutputparameterarray:{it|{add(new Parameter().builder().name("€it.Name€").type("{\"type\": \"€it.Type€\"\}").build());\}};separator="\n"€ \}; - return scipClientFunctions.performSubscribe(null,"€eventName€",parameters,input.getFilter(),input.getCorrelationIdentifier(), input.getDegreeOfConfidence()); + return scipClientFunctions.performSubscribe(null,"€event.Name€",parameters,input.getFilter(),input.getCorrelationIdentifier(), input.getDegreeOfConfidence()); \} @CrossOrigin - @RequestMapping(value = "/unsubscribe/€eventName€", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE\}) + @RequestMapping(value = "/unsubscribe/€event.Name€", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE\}) public UnsubscribeResponse unsubscribe€event.FirstCapital€() { List parameters= new ArrayList(){ - €eventoutputparameterarray:{it|{add(new Parameter().builder().name("€it.name€").type("{\"type\": \"€it.type€\"\}").build());\}};separator="\n"€ + €eventoutputparameterarray:{it|{add(new Parameter().builder().name("€it.Name€").type("{\"type\": \"€it.Type€\"\}").build());\}};separator="\n"€ \}; - return scipClientFunctions.performUnsubscribe("€eventName€",null,parameters,null); + return scipClientFunctions.performUnsubscribe("€event.Name€",null,parameters,null); \} };separator="\n"€ \ No newline at end of file diff --git a/SCTransformation/Visitors/JavaScriptVisitor.cs b/SCTransformation/Visitors/JavaScriptVisitor.cs index c1f1b4b..7d944c4 100644 --- a/SCTransformation/Visitors/JavaScriptVisitor.cs +++ b/SCTransformation/Visitors/JavaScriptVisitor.cs @@ -51,7 +51,7 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) JavaScript.Variables.Add(new JavaScript.Variable { Name = objectName, - Type = type + Type = type?? "string" }); } } @@ -60,14 +60,15 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) { var inputs = new List(); var outputs = new List(); - var eventName = string.Empty; + var events = new List(); + var hasSideEffects = false; foreach (var parameterArg in statement.functionDeclaration().formalParameterList() .formalParameterArg().Skip(1)) { inputs.Add(new JavaScript.Parameter { Name = parameterArg.assignable()?.identifier()?.GetText(), - Type = parameterArg.singleExpression()?.GetText() + Type = parameterArg.singleExpression()?.GetText() ?? "string" }); } @@ -82,18 +83,21 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) { foreach (var expression in bodyExpression) { - if (expression.GetText().ToLower().Contains("setevent")) + var text = expression.GetText().ToLower(); + if (text.Contains("setevent")) { if (expression.GetChild(1)?.GetType() == typeof(JavaScriptParser.ArgumentsContext)) { - eventName = expression.GetChild(1).GetChild(1).GetText(); + var eventName = expression.GetChild(1).GetChild(1).GetText(); + events.Add(eventName.Substring(1, eventName.Length - 2)); } } - if (expression.GetText().ToLower().Contains("putevent")) + if (text.Contains("putstate")) { JavaScript.IsStateful = true; + hasSideEffects=true; } } } @@ -109,7 +113,7 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) outputs.Add(new JavaScript.Parameter { Name = expression.GetText(), - Type = string.Empty + Type = "string" }); } } @@ -119,7 +123,8 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) { Name = statement.functionDeclaration().identifier()?.GetText(), Inputs = inputs, - EventName = eventName, + Events = events, + HasSideEffects = hasSideEffects, Outputs = outputs }); } @@ -135,14 +140,15 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) { var inputs = new List(); var outputs = new List(); - var eventName = string.Empty; + var events =new List(); + var hasSideEffects = false; foreach (var parameterArg in classElement.methodDefinition().formalParameterList() .formalParameterArg().Skip(1)) { inputs.Add(new JavaScript.Parameter { Name = parameterArg.assignable()?.identifier()?.GetText(), - Type = parameterArg.singleExpression()?.GetText() + Type = parameterArg.singleExpression()?.GetText() ?? "string" }); } @@ -153,21 +159,24 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) ?.singleExpression(); if (bodyExpression != null && bodyExpression.GetType() == - typeof(JavaScriptParser.SingleExpressionContext)) + typeof(JavaScriptParser.SingleExpressionContext[])) { foreach (var expression in bodyExpression) { - if (expression.GetText().ToLower().Contains("setevent")) + var text = expression.GetText().ToLower(); + if (text.Contains("setevent")) { if (expression.GetChild(1)?.GetType() == typeof(JavaScriptParser.ArgumentsContext)) { - eventName = expression.GetChild(1).GetChild(1).GetText(); + var eventName = expression.GetChild(1).GetChild(1).GetText(); + events.Add(eventName.Substring(1, eventName.Length - 2)); } } - - if (expression.GetText().ToLower().Contains("putevent")) + + if (text.Contains("putstate")) { + hasSideEffects = true; JavaScript.IsStateful = true; } } @@ -184,7 +193,7 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) outputs.Add(new JavaScript.Parameter { Name = expression?.GetText(), - Type = string.Empty + Type = "string" }); } } @@ -192,8 +201,9 @@ public override object VisitProgram(JavaScriptParser.ProgramContext context) methods.Add(new JavaScript.Function() { - Name = classElement.methodDefinition().propertyName().GetText(), - EventName = eventName, + Name = classElement.methodDefinition()?.propertyName()?.GetText(), + Events = events, + HasSideEffects = hasSideEffects, Inputs = inputs, Outputs = outputs }); diff --git a/SCTransformation/Visitors/SolidityVisitor.cs b/SCTransformation/Visitors/SolidityVisitor.cs index 229f61e..4b54bc9 100644 --- a/SCTransformation/Visitors/SolidityVisitor.cs +++ b/SCTransformation/Visitors/SolidityVisitor.cs @@ -184,6 +184,18 @@ public override object VisitSourceUnit(SolidityParser.SourceUnitContext context) }); }); } + + var events= new List(); + if (functionDefinition.block()?.statement() != null && functionDefinition.block()?.statement().GetType()== typeof(SolidityParser.StatementContext[])) + { + foreach (var body in functionDefinition.block().statement()) + { + if (body?.emitStatement()!=null && body.emitStatement().GetType() == typeof(SolidityParser.EmitStatementContext)) + { + events.Add(body.emitStatement().functionCall().expression().GetText()); + } + } + } var overrides = new List(); functionDefinition.modifierList()?.overrideSpecifier()?.ToList() @@ -199,7 +211,10 @@ public override object VisitSourceUnit(SolidityParser.SourceUnitContext context) Scope = Enum.Parse( functionDefinition.scopeDefinition()?.GetText() ?? "public", true), Parameters = parameters, + Events = events, ReturnParameters = returnParameters, + HasSideEffects = IsStateful(GetStateMutability(functionDefinition.modifierList() + ?.stateMutability().FirstOrDefault()?.GetText())), ModifierList = new Solidity.ModifierList { ModifierInvocation = new Solidity.ModifierInvocation @@ -257,9 +272,8 @@ private bool IsStateful(Solidity.StateMutability stateMutability) { return stateMutability switch { - //TODO: - Solidity.StateMutability.Constant => true, - Solidity.StateMutability.Payable => true, + Solidity.StateMutability.View => true, + Solidity.StateMutability.Pure => true, _ => false }; }