Processing signed contracts in a state machine: Open Vote example

The LegalLab repository contains a new example that illustrates how Neuro-Feature token state machines can be used to process signed smart contracts. The example implements a simple open voting system that tokenizes each vote, counting ballots within a given time frame, as they are cast. Each ballot is a smart contract signed by a participant. The state-machine of the vote counts accepted ballots, rejects incorrect ballots, and logs events to the Neuro-Ledger for transparency and auditability.

Note: The same architecture as exemplified by the Open Vote set of contracts (Vote + Ballot contracts) can be used in many technically similar (albeit conceptually different) cases. One such example is the tokenization of agriculture, for example, where each cultivation can be tokenized, and it can keep track of its current state transparently (for the end consumer) by processing observations, each observation recorded as a signed smart contract with information about what has occurred. Another example can be the tokenization of medical journals, for interoperability and privacy protection. The journal observes diagnoses and tests being performed, each one recorded as a signed smart contract with the appropriate information.

Vote Contract

The first contract in the Open Voting model (OpenVoteYesNoAbstain.xml), contains the state-machine Neuro-Feature token definition and contract. It defines the basic states of ballot processing. It assumes each ballot contains machine-readable information, as defined by the schema OpenVote.xsd, also downloadable online via its target namespace: https://paiwise.tagroot.io/Schema/OpenVote.xsd.

Note: Each contract containing machine-readable instructions will only be accepted if each Neuron® can validate the XML it contains. This is done by downloading the schema files from the corresponding target namespaces and using these schemas for validation. If the validation does not complete successfully, the contract is automatically rejected.

The states defined in the contract can be illustrated with the following state diagram:

Open Vote Contract State Diagram
Open Vote Contract State Diagram

The voting contract allows the creator to pose a question, define if participants are allowed to change their votes, and between what times the vote will be active. Times are defined in UTC. Participants need personal digital IDs with at least a validated country code, personal number and full name. Only one ballot per (Country, Country Code) will be counted. Apart from a Creator, the contract also requires a Certifier, which can be the same as the creator. The Certifier are given rights to cancel (invalidate) an election.

The states a voting procedure passes through are:

  • During the Preparing state, the state machine checks if it is paired with a Ballot template that points to it. The Ballot template needs to define a contract reference parameter to the vote, and it needs to enforce the template of the vote to match the template used to create the vote. If one such Ballot template is found, it progresses automatically to the next state. If one is not found, it awaits until such a template is approved on the Neuron®.

  • The Pending state, is a state where the vote is prepared, but has not commenced yet. During this state, the present view can be displayed, and links to the vote can be distributed. Any ballots cast during this state will be automatically rejected. Once the time to open the vote has been reached, the state-machine progresses to the next state.

  • The Open state is where participants can vote by signing Ballot contracts. If they are signed using the appropriate template, and pointing to the vote, the state-machine will process the ballots. If any errors are encountered, the corresponding ballot is rejected, and error logged. When the finishing time has been reached, the state-machine progresses to the next state.

  • The last state is the Closed state. Here, the voting machine is kept alive, to present results, but no ballots are processed, so the tally cannot be changed. Once the expiry time is reached, the state-machine is ended.

During state changes, the creator is notified by XMPP (Instant Chat Message) and e-Mail about the state of the vote. The messages contain links to the vote. These can be distributed to participants of the vote. The vote can also be shown in a browser. If published, voters and other participants can follow the results in real-time.

Ballot Contract

The second contract template is the OpenBallotYesNoAbstain.xml contract. It defines the ballot contract that can be used to participate in any votes generated by the corresponding voting template. The two templates must be paired. So, once the voting template has been proposed and apporved, its ID must be set into the Ballot template contract, before it can be proposed. Once this has been done, it can be proposed and approved accordingly. Then, the pair can be used with as many votes as desired.

The Ballot template defines the Boolean parameters necessary to be able to select Yes, No or Abstain. The Machine-readable part (defined by the https://paiwise.tagroot.io/Schema/OpenVote.xsd namespace) instructs the vote state-machine how the ballot is to be interpreted. The Ballot template has a contract reference parameter of a given name, and it must require a contract reference having a template ID restriction equal to the ID of the voting template. Once the voting state-machine is running, it will provide links to the corresponding Ballot contract template, with these references pre-set, so the user does not need to worry about providing the values for thse references. The user will only scan a QR code to vote.

Approved templates for experimentation

If you want to experiment with the open voting solution described, you can use the following approved contract templates. You can either copy the contract IDs and use in your application, or if you use an App, scan the corresponding QR code to access it.

To create a vote, i.e. define a question partiticpants will vote on, use the following template by scanning the code or entering its ID in the appropriate interface:

Open Vote Contract Template: 2fd5d98c-f73c-fdee-e401-6358b2596dfd@legal.sa.id.tagroot.io
Open Vote Contract Template: 2fd5d98c-f73c-fdee-e401-6358b2596dfd@legal.sa.id.tagroot.io

The matching Ballot template (which you will not need to scan here directly, as it will be presented pre-filled for you, see below), is:

Open Vote Ballot Contract Template: 2fd5d9a6-f73c-fdf3-e401-6358b2b88d43@legal.sa.id.tagroot.io
Open Vote Ballot Contract Template: 2fd5d9a6-f73c-fdf3-e401-6358b2b88d43@legal.sa.id.tagroot.io

After scanning the code, a new vote contract will be displayed. Fill in the details (question, if votes can be changed and the time interval the vote will be open; remember the times need to be provided in Universal Time Coordinates, or UTC). Sign the contract, both as Creator and Certifier (unless you want another person to sign as Certifier). Once the vote has been created and been properly signed, a Neuro-Feature token will be created. It will send you an e-mail with a link to the voting results page. The vote only passes slightly the preparation state, as an approved ballot template already exists. The vote page will look something as follows. Note the QR code to the right. It will point to the ballot contract template to use to cast a ballot, and also contain the reference to the current vote pre-filled. All you need to do after scanning the QR-code, is to select how you want to vote.

Note: The vote token is defined to be unique. This means, you can only create one token (one vote) with the same set of parameters. This means, you need to change any of the parameters from previous versions, including the question or time parameters, before you can create additional votes.

Vote Count & real-time presentation

The token that is generated by the vote contract has a present report that displays the current state of the vote. The creator can access the present report from the client used to create the vote contract, and by extension the token. The creator will also get an Instant Chat Message and an e-Mail, containing the present report and current vote count (which would be zero and pending, before the count starts). There will also be a web URL which can be distributed, that will show the vote to any online viewer. The URL will have a format similar to https://sa.id.tagroot.io/NF/a86d6033-b694-7b5e-c8d3-42d5200ec85c@edaler.sa.id.tagroot.io. The ID in the URL corresponds to the ID of the Vote. You can match this ID with the ID displayed for the vote (see below). The present report can be projected and displayed in kiosk mode as well. It will be updated in real-time as votes are counted. The initial view may be something as follows:

Pending Vote
Pending Vote

Note The QR code in the report can be scanned by participants, and will point to the ballot template, with the vote reference pre-filled in. All the participant needs to do, is vote, and sign the ballot and the vote will be counted. Once the vote closes, the report will be updated accordingly also.

Closed Vote
Closed Vote

Note: Once the vote closes, the QR code changes. It is no longer pointing to the ballot template, but instead to the token that performed the count. Scanning it will give access to the token, and the reports it publishes.

Presentation Layout

The layout presenting the vote count is generated by the voting token itself, and is part of the vote contract template, and can therefore be reviewed as well. It is an XML Layout format, availble in the OpenVoteResultLayout.xml file. You can edit such XML files and preview the layout using LegalLab as follows:

LegalLab XML Editor
LegalLab XML Editor

The variables and script functions used in the layout need to be initialized. This can be done in the Script tab. You can use the initialization script published in the repository: OpenVoteResultLayoutInit.script to generate the view above.

Neuro-Ledger entries recorded

Apart from all entries recorded regarding Digital Identities, Smart Contracts, Tokens and State-Machines, the Open Vote example records several entries by itself. These include:

Entry Description
BallotCounted A ballot has been counted.
BallotRejected A ballot has been rejected.
BallotRevoked When an older ballot has been revoked because the participant submits a new ballot.
CommentReceived A comment by a participant has been received.

Note: The vote contract defining the vote, also defines the Neuro-Ledger Collection these entries are recorded in.

The other common Neuro-Ledger collections annotating entries are:

Neuro-Ledger Collections
LegalIdentities Contains entries related to digital identities, including Neuro-Access digital identities.
Contracts Contains entries related to smart contracts, including the voting contract and the ballot contracts used during voting.
NeauroFeatureTokens Contains information regarding Neuro-Feature tokens, including the token definition of the open voting logic.
StateMachines State-Machine information is recorded in this collection. This includes the open voting process performing the ballot counting and presentation.
StateMachineCurrentStates Contains current states of different State-Machines.
StateMachineSamples Contains variable changes as they are persisted by State-Machines. These samples can be used to track the counting process.

#tutorial, #example, #legallab, #contracts, #neuro-feature, #neuro-ledger, #state-machine


Bug Fixed: Misspelling in State-Machine interface

A relatively consequential misspelling has been corrected in the State-Machine object model on the Neuron®. The property that holds the XML definition of the state-machine was mistakenly named XmlDefinnition. It has now been corrected to XmlDefinition, from build 2023-09-25 of the Neuron®. This change may have some consequences:

  • Serialization and deserialization of state-machine objects during Loading and persistance is done automatically. In this process, the old, and now obsolete XmlDefinnition property is automatically transformed into the new XmlDefinition property, if this persistance or loading is done in a typed manner, i.e. knowing what type of object is being processed. This is the default case when processing state-machines and their events, in normal processing.

  • The automatic conversion is not performed if untyped access to the state-machine object is performed. This can be done, for instance, when processing content using SQL or SPARQL queries, accessing the collection directly, without referencing specific types (i.e. using generic types).

Consequences

This change can have unintended consequences for all untypes access to the State-Machine object model. In the Neuron®, this only happens during backup, import or export of the database, or from third-party applications performing untyped access to the database. We are aware of no such third-party service that presents the state-machine XML definition, so no unintended consequences are expected.

Note: This misspelling does not affect the smart contracts and Neuro-Feature tokens creating the state-machine. It only relates to the internal object model for maintaining a running state-machine on the Neuron®.

#bug, #fixed, #state-machine


Note commands in state-machine neuro-feature tokens

One way to interact with state-machines defined by Neuro-Feature™ tokens can be done using notes. Such notes can be either text or XML, and they can be either logged by the owner of a token creating the state-machine, or by approved external sources. All notes are logged also to the Neuro-Ledger™, for transparency reasons. For XML-tokens, an additional XML-validation is performed, before accepting a note: The XML must use publicly downloadable schema-files, and the XML must be valid, in accordance with these schema files. Personal notes are deleted, if the tokenⓈ change owner.

Until build 2023-09-22 of the Neuron®, owners and external sources had to know the syntax of such notes, to interact with the state-machines. The token, and underlying state-machine, can now instead describe what notes are available, under what contexts they are available, and how they are formed, in a way that is both understandable by machines, and humans. It is therefore possible to create user interfaces automatically and generatively, directly from the state-machine definition. LegalLab has also been updated to support such note commands, as have the corresponding example contracts in the repository.

Example: Digital Sensor Twin

The DigitalSensorTwin example contains several context-specific note commands. The owner can poll the sensor, pause reading, resume reading, reconfigure the digital twin, and terminate it. Some of these commands are parameter-less, others are parametrized. Parametrized note-commands require the user to fill in a form before the note can be logged. All XML-based commands use a corresponding schema file, available in the repository, and also downloadable from the corresponding namespace URL.

In the following example, LegalLab is used to create a digital sensor twin of a weather station, available at the XMPP address concon.openweathermap@lab.tagroot.io.

Creating a Digital Sensor Twin
Creating a Digital Sensor Twin

Once the contract has been created and signed, the token is created, together with the state-machine of the digital twin of the sensor. The corresponding token appears in the Tokens tab. Note commands, defined in the token itself, will now appear in both the context menu, as well as in the token details view.

Note Commands for Token
Note Commands for Token

Parametrized note commands

As an example of a parametrized note command, let’s review the Reconfiguration command in the digital sensor twin, and how it is defined:

Reconfigure Note Command
Reconfigure Note Command

The parameters are defined in a similar manner, as contract parameters. An optional note context script can be added to tell the client under what conditions the command is visible. The script is run on the client, is checked to be safe, and can include references to the state or internal variables of the state-machine to evaluate if the command should be visible or not. The script should return a Boolean value. Anything else, will hide the command.

Once the command is executed, the note generation script is executed, and should return either a text string (for text notes) or XML (for XML notes). Anything else is ignored. If text or XML is returned, this is the basis for the note that will be logged.

Note: To avoid confusion as to what is XML, and what is script, it may be a good idea to always embed script in CDATA constructs, as shown in the example. This becomes especially important, if the script also contains XML, as in this case.

Parameter-less note commands

If a note command does not require parameters, simply skip the Parameters section in the definition. Such commands may still be context-sensitive, for instance, be based on the current state of the state-machine, or its internal variables. You can try such commands by testing the Pause and Resume commands of the digital sensor twin. The Pause command is only available in the active state, while the Resume command is only available in the Paused state.

PauseAndResumeCommands.png
PauseAndResumeCommands.png

State-Machine Schema

The most recent schema for State-Machines is always available by downloading the schema from its URL, which is the same as its namespace: https://paiwise.tagroot.io/Schema/StateMachines.xsd. It contains the details, what attributes are available, as well as what is required and what is optional.

#neuro-feature, #new, #state-machine, #legallab


Bug Fixed: State machines did not persist the beforeActionScript attribute

State-machines using the beforeActionScript attribute on action reference nodes, such as event handlers, have lost their corresponding attribute values after restart. The reason is that the attribute value was not persisted.

Cause

The root cause of this is that the property was declared incorrectly. To be persisted, an attribute needs to have a public get and set method available, for the persistance layer to be able to persist it. Persistence is implicit, and no code is written explicitly to persist or load objects. Instead, the persistence layer relies on the declaration of the properties to persist. In this case, this particular property lacked such get and set methods.

Background

The beforeActionScript attribute was introduced to provide a means to re-use actions for different types of events. It allows the event handler to customize the execution of the action, by (for instance) providing variable declarations. (In such cases, the before-action script would work as assigning argument values in a function or method call in procedural or object-oriented programming languages.)

Tests

The problem was not detected in unit tests, since these are implemented in such a way to create new state machines for every test, to not rely on earlier execution, and therefore, they did not test more than the operation (which worked), and that persistance occurred without error. The tests missed that this particular attribute was lost once loaded after server restart.

Fix

The attribute is now declared properly, and value is persisted.

Review

After a review of the entire state machine model, it is concluded that this attribute was the only attribute that lacked a proper declaration.

Affected tokens

This problem affects generated tokens on Neurons with a build-time before 2023-09-21, if and only if they used the beforeActionScript attribute. After update, new tokens generated will persist the attribute correctly. Upgrading your Neuron® to a newer version, will not resture the attribute value.

Repair

A new method has been added to the State-machine object: ReparseDefinition(). As the original XML of the state-machine is available (and kept immutable in the token), the lost attribute can be regained by calling the ReparseDefinition() method on each state-machine, resave the objects, and then restart the Neuron®, for the changes to take effect.

Following is some script you can execute in the script prompt to re-parse all state-machines on the Neuron®. It will return a vector of all state-machine-IDs processed. Depending on the number of state-machines, complexities of the models, etc., execution of the script may take some time. (You can adapt this script if you want to apply it only to specific state-machines.) Make sure to take a backup before executing the script.

preview("Loading state-machines. This may take some time.");
Machines:=select * from StateMachines;
[foreach Machine in Machines do
(
	preview("Processing "+Machine.StateMachineId);
	Machine.ReparseDefinition();
	UpdateObject(Machine);
	Machine.StateMachineId
)]

Note: All changes to the operational state of the state-machine, as well as script executed via the script prompt, will be logged, both to the event log, as well as to the Ledger.

Note 2: If expecting many state-machines to be processed, you can use the TOP and OFFSET operands in the select statement, to paginate the processing into chunks.

Note 3: Keep the event log sniffer open while processing the script, to check for any unexpected events.

Note 4: Test this script in your lab/development environment first, and consider whether you need the update in your production environment or not, before applying the change. You can also modify the script to only process the state-machines you decide are important to update, to minimize any risks when performing the update.

#bug, #fixed, #neuro-feature, #state-machine


Posts tagged #state-machine

No more posts with the given tag could be found. You can go back to the main view by selecting Home in the menu above.