...by Daniel Szego
quote
"Simplicity is the ultimate sophistication."
Leonardo da Vinci

Wednesday, January 4, 2017

Serializing state into the Blockchain in Decentralized Business Process Management

Well serializing state for Decentralized Business Process Management (or simply DBPM) does not seem to be very complicated for the first sight If we consider Ethereum as a Blockchain solutions. Let we assume that we have custom workflow for approving a project budget, having the following properties: ProjectName, ProjectType, ProjectBudget.The first intuitive realization is a simple smart contract, called WF_ProjectBudget having the three properties as parameters and having a set get function for each: 

contract WF_ProjectBudget
{
 string ProjectName;
 string ProjectType; 
 int ProjectBudget;
 
    function setProjectName(string _ProjectName)
    {
        ProjectName = _ProjectName;
    }
    
    function getProjectName() constant returns (string)
    {   
        return ProjectName;
    }

    function setProjectType(string _ProjectType)
    {
        ProjectType = _ProjectType;
    }

    function getProjectType() constant returns (string)    {
        return ProjectType;
    }
    
    function setProjectBudget(int _ProjectBudget)
    {
        ProjectBudget = _ProjectBudget;
    }

    function getProjectBudget() constant returns (int)    {
        return ProjectBudget;
    }
}

There is a problem however with this intuitive approach. As the parameters can be set one by one, there is no guarantee that they will be set in an atomic action, meaning that either all of the values change or none of them. Supposing that atomic action is required saving the workflow state, the following code might describe the situation better:

contract WF_ProjectBudget
{
 string ProjectName;
 string ProjectType; 
 int ProjectBudget;
 
    function getProjectName() constant returns (string)    {   
        return ProjectName;
    }

    function getProjectType() constant returns (string)    {
        return ProjectType;
    }
    
    function getProjectBudget() constant returns (int)    {
        return ProjectBudget;
    }

    function setWFState(string _ProjectName, string _ProjectType, int _ProjectBudget) {
        ProjectName = _ProjectName;
        ProjectType = _ProjectType;
        ProjectBudget = _ProjectBudget;
    }
}


It is important to note that although the construct seems to be pretty simple, it guarantees that the three values are set in an atomic transaction independently of any kind of possible errors, like network outage, validation node failure or heavy cyber attack.

In real life scenarios we should consider that not always the whole state but only a part of it is saved in a transaction. As a consequence, it might make sense to explicitly define atomic groups: group of variables that should be serialized together. Another drawback is that this model assumes the one contract - one workflow model. A more general model might be to work with structs instead of individual variables, in this way one general solidity contract can contain the storage interface for several different workflows:

contract WF_State
{
    struct ST_ProjectBudget{
     string  STProjectName;
     string ProjectType;
     int ProjectBudget;
    }

    ST_ProjectBudget LatestProjectBudget;

    function WF_State(string _ProjectName, string _ProjectType, int _ProjectBudget)
    {
        LatestProjectBudget = ST_ProjectBudget(_ProjectName, _ProjectType, _ProjectBudget);
    }

    function getProjectName() constant returns (string)    { 
        return LatestProjectBudget.ProjectName;
    }

    function getProjectType() constant returns (string)    {
        return LatestProjectBudget.ProjectType;
    }

    function getProjectBudget() constant returns (int)    {
        return LatestProjectBudget.ProjectBudget;
    }

    function setWFState(string _ProjectName, string _ProjectType, int _ProjectBudget) {
        LatestProjectBudget.ProjectName = _ProjectName;
        LatestProjectBudget.ProjectType = _ProjectType;
        LatestProjectBudget.ProjectBudget = _ProjectBudget;
    }
}