Some tips on smart contract migration to Azure Blockchain Service (Quorum)

Tools Versions

The first thing to check is the version of the various tools that are necessary for the creation and migration of the various smart contracts. To check the version of the various tools just use the following command line

It is essential to adopt exactly the versions as shown in the figure, especially as regards the version of Web3.js which must necessarily be 1.0.0-beta.37. It is also necessary to make sure that the Python version is 2.7

New Account

At this point it is necessary to create a new account within our blockchain. We declare the network with all its features in the truffle-config.js file

Then we connect to the node through a truffle console and use the following command line:

Truffle-config.js

We modify the truffle-config.js through the insertion of the new account that we will use for the migration:

Now Migrate!

We underline an important point. As we see in the figure we had to insert a directive concerning the solidity compiler. When we entered the indication on the type of Virtual Machine (in our case the 'byzantium' which apparently is not the default one), our migration was successful through the following command line:

I recommend using the --reset option

 

Using Nethereum.Web3 to implement a Supply Chain Traking System

Source Code

All code used in this post (C#, Solidity, DB scripts) can be downloaded at my Git repository

Intro

I had the opportunity to test the Nethereum.Web3 library by implementing a Supply Chain Traking System (SCTS) project and it proved extremely interesting from different points of view. During this post we will see how you can interact from .NET code with a BlockChain Ethereum making calls to Smart Contract methods.

 

What is a Supply Chain Tracking System (SCTS)

There is an official implementation of such a system that you can download at this address https://github.com/AtrauraBlockchain/scts. The definition that is given is this:

"STCS is a smart contract to keep track of products from the raw materials to the shopping stage." This system is powered by the Ethereum Blockchain, so it's fully distributed, immutable and auditable ". The version, however, here implemented differs a lot in the process flow architecture and in the relationship between entities. In practice we have this type of flow:

A Handler (which can be any user who manipulates the product at a certain stage of the transport chain) at some point takes charge of a product and applies an action to the same product (for example "I take the product from the Handler2", or " Deposited the product in Warehouse X "). A Handler is always associated with a user who must log in and to which always corresponds an Ethereum Address as an Ethereum Account . Every action applied to that product and performed by a certain Handler is memorized in the BlockChain and can be subsequently retrieved reconstructing the history of the product itself. Actions can be applied until the product reaches its destination and at that point is considered "consumed" and no action can be associated with it. Here is a process flow diagram:

Web Application

The application consists of a .NET Core 2.0 web portal which is accessed through the IdentityServer. The Database was constructed in such a way that each account was associated with a BolockChain Address (Account Ethereum), so that a column was associated to the AspNetUsers table of Identity Server

To be able to return the BC Address at the time of authentication, IdentityServer will insert this information into a claim that will be added to the predefined claims collection that Identity returns in the token of the user who has just accessed the portal. To make everything simpler we have chosen to extend the ApplicationUser class with a property that will contain the BC Address:

And now we come to the MVC application. First we need to add the Nethereum.Web3 package via Nuget

Now we have all the ingredients to interact with our Blockchain, we will see later the part of the Smart Contracts involved in the implementation on the Ethereum side. Once logged in the portal we can browse the product page where the list of products already entered is displayed. This page begins with a call to the BC to interrogate a smart contract "Database" that contains all the products. As we can see, the page contains the BC Address on the top, as evidence of the association between this and the username in the upper right corner

The page must necessarily execute some calls to BC Ethereum in order to retrieve the list of products. So here the use of our Nethereum library begins. Let's see the code in detail. First of all, the claims containing the Ethereum address of the user are retrieved from the IdentityServer. Once retrieved, we read from the configuration file the address of the Ethereum network that we give to the Web3 class constructor to define the instance representing the context of the Blockchain where we will operate.

With the Web3 instance we can now access the smart contracts published in the BC and invoke the methods. To invoke a method of a smart contract it is necessary to obtain the ABI (Application Binary Interface) and the address of the contract itself. What is an ABI for? We must think that a smart contract in bytecode was distributed in Ethereum. When we want to invoke a method then we must follow an extremely rigorous formalism that forces the caller to pass the parameters of the call in a way that perhaps is not usual to those who program only in high-level languages. Following the specifications of the Ethereum documentation we can see how to call a method with two whole parameters in input it will be necessary to pass 68 bytes to the call to the BC. It starts from the first 4 bytes which are the first 4 bytes of the result of the hashing operation of the method signature. Example if the method has the following signature

function baz(uint32 x, uint32 y) public pure returns (bool r)

then the first 4 bytes of the operation are taken

bytes4(keccak256("baz(uint32,uint32)") = 0xcdcd77c0

then follow 32 bytes for the first parameter (padded 0) and the other 32 bytes of the second parameter (padded 0). The thing is evidently much more complex than the passages of parameters of high-level languages where everything is hidden by compilers, which however always adopt ABI hidden mechanisms at a high level, but absolutely present at the machine language level. To take a further example, let's think about the function calls of functions at the assembler level. In that case the stack represents the portion of memory that contains the ABI for the call to function by the caller.

Where do we find the ABI of a contract? The Solidity compiler provides it when it compiles a smart contract and the result will be a Json file containing among other things also the bytecode of the contract itself:

Above is shown the portion of ABI in Json format relative to the 'getProduct' method which in input wants an integer and returns the address of the relative contract.

For convenience, a 'BlockChain' class has been built containing all the ABIs and all the Addresses of the contracts. Finally, the contract address is very simple to retrieve during the contract migration phase. We have used Ganache as a Blockchain Ethereum using the default addresses provided

In our case the smart contract Database has address 0xde554c0b4ca9efcf1958c01485d673a0b06d5bc1

Let's get ready for the various calls

We recover the Contract object that our library abstracts for us with good results. The Function object is then retrieved which abstracts the method present in the smart contract and then the asynchronous call to the method is made. This call returns to us the number of Product Smart Contract really recorded in BC. For each of these we will invoke another function of the Smart Contract Database to which we will pass the cycle index, returning the address of the smart contract. Once the address of the Product has been retrieved, we will retrieve the names of the product properties and read them through appropriate calls as shown:

With the properties of each Product we will create the corresponding DTO to be included in the model to be displayed on the page. Now let's insert a new product. That is, we imagine that a new product is created within the company, or a new batch of materials that will then be sent to the end customer:

To get more precision we also store the location where the product was created. Once created we see it in the list:

How did the creation of a new smart contract product work in the blockchain? In this case the operation obviously has a cost (in Gas) unlike the consultation operation that does not change the status of the Blockchain and therefore does not require any contribution in Gas. To prepare the call data we construct an object that contains among other things also the Gas to 'pay' the transaction in addition to the other parameters that consist of the product name, additional information (product description) and geographical coordinates in addition to 'address of the smart contract' Database '. Here is the code in detail:



Now we add an action to the product. For example, let's say that the product has been stored in the main warehouse

The technique from the point of view of Nethereum is the same as the previous transaction that created the Product contract. In pratical invoking a method to retrieve the address of the Product contract to which to add an action, setting the parameters to invoke 'addAction' to the contract and view the product history. If at this point the product was delivered to another user, an action would be added and, by accessing another account, the whole chain of steps would be displayed, representing the various actions performed on the product up to the end user (at this point we say that the product is 'consumed' and any other further action is not permitted), which could use an app to verify the whole chain of steps seeing that the product has followed a certain path from leaving the factory until you get to him.

Smart Contract

We come now to the solidity part. There is a basic contract called Owned from which the DataBase contract is derived, for example, and which allows operations to be performed on the latter only if the initial (user) address has been configured.

The Database contract also contains the following features to manage the contracts within it:

Here instead I reproduce the code of the contructor of the Product, which has as its parameter the address of the contract database and this will be very interesting to see it during migration

Here is how a migration file must be made that contains a contract (product) inside it, which in order to be initialized must wait for the creation of the Database contract and receive its address

 

Conclusions

The SCTS system implemented through Blockchain Ethereum guarantees the total integrity and immutability of the various steps that characterize the life of a product. The more the product is characterized by a univocal recognition, the more this chain guarantees maximum reliability, offering guarantees regarding the integrity of the product in addition to its origin (we think, for example, the great use that can be made to guarantee the authenticity of some Made in Italy products). The code as tradition can be retrieved from the git project that contains, in addition to the C # code, also the script to generate the DB and the smart contract solidity code to be created in Visual Studio Code. The users already entered are the following:

account00@pomiager.comaccount01@pomiager.com, account03@pomiager.com, account07@pomiager.com, account09@pomiager.com 

All use the same password Pa$$w0rd

Happy code!

 

Using REST API in Azure Workbench Blockchain

Code

You can find all the code of the Web App WebClientWorkbench with calls to the Azure Workbench Blockchain Rest APIs here (Git Repository)
You can find the HelloBlockchain sample code here

Intro

We started using Microsoft Workbench Blockchain to implement an OpenBedge management application through the Blockchain. Following the official Microsoft tutorial we finally got the Blockchain version recently made available by the Redmond house. Prerequisites to follow the example of the post is the presence of a Workbench Blockchain distribution on Azure and the creation of the HelloBlockchain test application that you can find in the examples available on Git. In this post instead of using the administration app provided by default during the creation of the distribution,a Web App (.NET Core) will be used which, through calls to the Rest API services  will interact with the HelloBlockchain application. The scheme is as follows:

 

Azure Active Directory App registration

Our Web App will use Azure Active Directory for authentication, thus exploiting the Oauth2 integrated authorization mechanism. This must be implemented by registering an app in Azure Active Directory with the features we will see shortly. Once the user has accessed our Web App using the credentials of a User in Azure Active Directory, it means that he has obtained an Authentication Token (Auth Code). In order to invoke the Blockchain APIs, however, the Web App must use its own Authentication Token (Auth Code) to obtain an Access Token to the Blockchain API resource. Once you have the Access Token you can finally use it (by inserting it in the request header) to invoke the Blockchain's Rest API. The scheme is:

Let's start by creating a new Asp.NET core MVC project in Visual Studio and write down the default URL (eg http: // localhost: 51369). Now we're going to register an app in our Azure portal. From the Active Directory menu go to the "Registration App" blade and start recording our app with these features:

It will be essential to provide our newly registered app with two key features. The first is a key called ClientSecret that will be useful to prove your identity, i.e. your credentials, when requesting an Access Token. The second will be the authorization to use the Blockchain API. In this way, when an Access Token is requested, it will be created embedding in it the authorization to use the Blockchain APIs. For the key go to the Properties of the app just registered and enter the blade Keys and produce the key, taking care to immediately store it as soon as it is created otherwise we will not be able to recover it.

At this point we enter the "Required Permission" blade and advance to the selection of the API to be authorized. In the API search text file, enter the name of the API created during the Azure Workbench Blockchain deployment. We kept the default name "Blockchain API" as we can see from the list of registered apps:

It will be shown the possibility of assigning the app to use the blockchain as a Global Administrator or just to access the APIs. We choose this second option:

Finally to complete the operation we must not forget to click on the "Grant Permission" button, otherwise we will have only set the permissions, but we will not have activated them

We note the Application ID and Client Secret. We'll also need to take note of the ID of the Blockchain API app and the base URL by going to see the app's properties. Other information to note is the tenant domain name that we use, the Tenant ID (which is the unique ID of our Azure Active Directory). With this informations we return to our .NET Core Web Application and set the appsetting.json file with these features:

Web App Asp.NET Core

And we come to our web application. Let's try now to test if the flow we have described above really works.

We have available a controller (Accountcontroller) that at the moment of clicking on the "Sign In" it redirects us to the default Microsoft Endpoint to be able to log in to our Azure Active Directory. This allows us to use AAD users who are automatically mapped to Ethereum's address transparently by Workbench.

We insert a Controller called BlockchainController to which we assign an action called Index that will contain a first call to the Blockchain API requesting the list of the Application Objects present in our distribution. Inside the method the code looks like this:

 

// Because we signed-in already in the WebApp, the userObjectId is know
                string userObjectID = (User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;

                // Using ADAL.Net, get a bearer token to access the WorkbenchListService
                AuthenticationContext authContext = new AuthenticationContext(AzureAdOptions.Settings.Authority, new NaiveSessionCache(userObjectID, HttpContext.Session));
                ClientCredential credential = new ClientCredential(AzureAdOptions.Settings.ClientId, AzureAdOptions.Settings.ClientSecret);
                result = await authContext.AcquireTokenSilentAsync(AzureAdOptions.Settings.WorkbenchResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

                HttpClient client = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.WorkbenchBaseAddress + "/api/v1/applications");
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                HttpResponseMessage response = await client.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    JsonSerializerSettings settings = new JsonSerializerSettings();
                    String json_string = await response.Content.ReadAsStringAsync();
                    ApplicationReturnType applicationsResponse = JsonConvert.DeserializeObject<ApplicationReturnType>(json_string);

                    List<IQC_WebClient_Workbench.Models.Application> applications = applicationsResponse.Applications
                    return View(applications);
                }

 

Having already logged into my Web App via the Sign In link at the top right, I have already obtained an Authentication Code and therefore the userObjectID is already known, which I will use later to create a unique identifier. I create an AuthenticationContex that uses a Cache to store the already requested Access Tokens and possibly not ask them for each request. In our case we have built a class that inherits from TokenCache that uses the Session to store Access Tokens. I create credentials using the app ID registered in Azure Active Directory and its associated Secret Client. At this point you just have to invoke "AcquireTokenSilentAsync (String, ClientCredential, UserIdentifier)" to get my Access Token.

Once obtained, use it as a header value (header Key = "Bearer") for the request to the Blockchain API. The request uses the url "/api/v1/applications" to which the base URL stored in a key must be placed in the appsettings.json. If everything is OK, the Blockchain API will return the list of Applications in the Workbench distribution

 

How Workbench REST API works

Let's start with the application ID that is important to us. In our case we see that HelloBlockchain has the iD 1. Let's use it to get the application Workflows. Workflows are the flows that describe exactly the status changes that the various contracts of the application make as a result of calls of functions of the related Smart Contract. Our application is extremely simple and contains only one workflow with just one HelloBlockchain type contract. Workbench has a very interesting approach because it considers the application as a finite state machine where each contract precisely follows a workflow passing from one state to another. In our case the application workflow is this:

As we see, once created, the contract goes into the Request state. In this state we can invoke a function of the smart contract (sendResponse) that will bring the contract into the state of Respond. At this point the contract can return to the status of Request again invoking SendRequest and will remain here waiting for a subsequent response. Who can invoke the methods of smart contract? Users obviously belonging to the roles of competence (Requestor and Responder). Users are those of AAD and the Workbench Admin can assign the correct roles from the Dashboard that is created by default at the time of distribution.

In correspondence to all this in the solidity smart contract we can see:

States become an enum in solidity. In the SendRequest function, it is checked that the address Ethereum of the invoker is the same as the Requestor stored at the time the contract is created as shown in the constructor's code:

(Note that the Workbench compiler does not yet support the keyword 'constructor' for which you need to write a function with the same name as the Smart Contract which is rightly reported as a warning from Visual Studio Code). The Requestor and the Responder are the addresses of Ethereum in correspondence of those who make requests and those who answer. The passage of states is described in the HelloBlockchain.json file that must be fed to Workbench when the application is created. But let's focus on the API again, leaving the in-depth description of the Workbench elements in another post.

After recovering the usual Access Token (which in the meantime may have been renewed silently) here is the invocation to receive the workflow of our application:

 HttpClient client = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.WorkbenchBaseAddress + "/api/v1/applications/1/workflows");
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                HttpResponseMessage response = await client.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {

                    JsonSerializerSettings settings = new JsonSerializerSettings();
                    String json_string = await response.Content.ReadAsStringAsync();
                    WorkflowReturnType workflowResponse = JsonConvert.DeserializeObject<WorkflowReturnType>(json_string);

                    List<IQC_WebClient_Workbench.Models.Workflow> workflows = workflowResponse.Workflows;


                    return View(workflows);
                }

Here is the result of the call:

Similarly for when contracts related to a workflow are required (in our case there is only one contract type - HelloBlockchain):

 HttpClient client = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.WorkbenchBaseAddress + "/api/v1/contracts?workflowId=1");
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                HttpResponseMessage response = await client.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    JsonSerializerSettings settings = new JsonSerializerSettings();
                    String json_string = await response.Content.ReadAsStringAsync();
                    WorkflowInstancesReturnType workflowistancesResponse = JsonConvert.DeserializeObject<WorkflowInstancesReturnType>(json_string);

                    List<IQC_WebClient_Workbench.Models.Contract> contracts = workflowistancesResponse.Contracts;
                    return View(contracts);
                }

Naturally for the sake of simplicity we have hardcoded some parameters within the URLs. The result of the contracts is this:

Very interesting now is the creation of a new contract that must be made (according to official documentation) through a POST call to the relative URL. After creating a simple form for the collection of the text of the Request Message (remember that the constructor in solidity wants the string of the request message) and taking care also that the user with which we are logged belongs to the role of Requestor, we will be able to make a call to create a new contract. Here is the list of my users and their respective roles taken from the dashboard:

Here is the request form:

At this point the final code. In the documentation it is clear that a Json must be prepared in the WorkflowActionInput format with relative properties containing among other things also the RequestMessage. Once serialized and inserted in the payload of the request the answer that is obtained is the ID of the new contract entered (there is an error in the official documentation at this time).

Pay more attention because in the documentation it is reported that some parameters included in the query string are optional, but in reality after receiving some error messages, investigating with Fiddler it turns out that the parameter workflowId is actually mandatory

After fixing the correct URL and received the new contract ID we make an additional request to view the new contract in a new page:

 HttpClient client = new HttpClient();
                client.BaseAddress = new Uri(AzureAdOptions.Settings.WorkbenchBaseAddress);
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/contracts?workflowId=1&contractCodeId=1&connectionId=1");
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                request.Content = new StringContent(jsonObject.ToString(), System.Text.Encoding.UTF8, "application/json");
 
                HttpResponseMessage response = await client.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {

                    JsonSerializerSettings settings = new JsonSerializerSettings();
                    String json_string = await response.Content.ReadAsStringAsync();
                    int newContractID = JsonConvert.DeserializeObject<int>(json_string);

                    HttpRequestMessage newRequest = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.WorkbenchBaseAddress + "/api/v1/contracts/" + newContractID);
                    newRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                    HttpResponseMessage newResponse = await client.SendAsync(newRequest);

                    if (newResponse.IsSuccessStatusCode)
                    {
                        String new_json_string = await newResponse.Content.ReadAsStringAsync();
                        Contract newContract = JsonConvert.DeserializeObject<Contract>(new_json_string);

                        return RedirectToAction("ContractDetail", newContract);
                    }

Here is the result:

Summary

In this post we saw how to use the Azure Workbench Blockchain API. The Workbenchclient that can be found in the example codes on Git was not intentionally used because we wanted to highlight in detail the direct calls to the APIs. Surely this technique allows you to build custom applications once you have created smart contract in solidity. We have noticed how, given the extreme simplicity of contract deployment and the management of users and their roles (which makes transparent a series of operations on Ethereum to be carried out to manipulate account addresses), it is initially difficult to disengage from structure of the applications that must follow the system of workflow and finite-state development. For many applications, however, this approach is certainly the best one.

See at the top of this post the link for the shared code.

Happy chain!