# Vocdoni protocol - next steps
## 1. Extend Vochain Accounts
#### a. Add zk friendly key to vochain accounts
Adding a babyjubjub key to Vochain accounts would enable two key features on the Vochain blockchain:
1. It would allow for the use of the Vochain as a public registry for relating a zk-friendly key to an Ethereum-compatible address. This would enable third-party projects to use zk-SNARKS technology with Ethereum addresses.
2. It would allow for the creation of internal censuses from Vochain accounts using zk-SNARKS voting.
#### b. Attach Ethereum addresses to an existing account
Linking Ethereum addresses to existing Vochain accounts allows users to connect multiple Ethereum addresses to a single Vochain account. This feature is useful for creating censuses based on Ethereum data. An Ethereum organization can scan the Vochain accounts for Ethereum addresses that need to be included in the census (i.e they own some NFT or are ERC20 holders) and only those Ethereum holders with a Vocdoni account will be able to participate in the governance. This allows for the usage and management of smaller and filtered censuses, providing greater flexibility and positioning the Vochain as a governance platform (only those users registered are elegible for voting). The resulting census might be constructed out of the zk-friendly keys, thus enabling anonymous voting for the Ethereum ecosystem.
#### c. Organization special accounts
Organization special accounts would create a new type of meta-account for organizations on the Vochain blockchain. These accounts would not have a private key associated with them, but other accounts would be able to manage them. This would allow organizations to participate in the Vochain ecosystem and enable the creation of simple decentralized autonomous organizations (DAOs) on the Vochain blockchain.
With this change we create a distinction between account and organization (currently both concepts are mixed), providing then a better experience and more clarity for the end user.
#### d. Delegate voting based on organization
Delegate voting based on organization would allow for the delegation of voting rights to organizations rather than individuals. This would enable organizations to make decisions on behalf of their members, rather than requiring each member to vote individually. An account would be able to define another account that would act as a representative. The representative could be set for all organizations or for a specific list of them.
----
### Implementation
#### Data models
The Account data structure needs to be modified and new ones need to be created, this is a proposal for the **Protobuf models**:
```protobuf
message Account {
uint64 balance = 1;
uint32 nonce = 2;
bytes babyjubjubkey = 3;
repeated bytes linkedAddresses = 4;
repeated Delegation delegates = 5;
optional bytes defaultDelegate = 6;
}
// indexed by account address (ethereum compatible)
```
```protobuf
message Delegation {
bytes organizationId = 1; // must be unique on Account delegates list
bytes account = 2; // must be a valid Vochain account
}
```
```protobuf
message Organization {
string name = 1; // name for the organization, length > 6 chars
bytes owner = 2; // address of the organization owner, can change
string infoURI = 3; // ipfs URL with the organization metadata
repeated bytes managers = 4; // list of management Accounts
uint32 electionIndex = 5; // number of elections created
uint32 censusIndex = 6; // number of census created
}
// indexed by organization ID (hash{initialOwnerAddress + name})
```
#### transactions
Transactions also need to be modified, this is a proposal:
##### 1. setAccountTx
```protobuf
message SetAccountTx {
TxType txtype = 1;
uint32 nonce = 2;
optional bytes account = 3; // used on CREATE_ACCOUNT
optional LinkAccountProof linkingProof = 4;
optional FaucetPackage faucetPackage = 5;
optional bytes defaultDelegate = 6
repeated Delegation delegates = 7;
}
```
```protobuf
message LinkAccountProof {
bytes address = 1; // ethereum address requested to be linked. Should not exist as Account and should not be already linked for this account.
bytes signature = 2; // signature over the address with its privKey
}
```
txType can be one of the following:
+ CREATE_ACCOUNT: creation of a new Vochain account. The babujubjub key can be added on this transaction. A valid faucetPackage must be used. A defaultDelegate can be set. No more Account fields are allowed on this transaction.
+ ADD_ACCOUNT_DELEGATES: adds one or multiple new entries as organization delegates for an Account.
+ DEL_ACCOUNT_DELEGATES: removes one or multiple delegations.
+ LINK_ADDRESS: links a new Ethereum address to an Account. The address must not exist as an Account in the Vochain. There is no check against having the same address linked by multiple accounts.
+ SET_BABYJUBJUB_KEY: sets (add or change) the zk friendly key for an Account.
+ DEL_ACCOUNT: removes the account. If there is an organization where the account is owner, the transaction must fail.
##### 2. setOrganizationTx
```protobuf
message SetOrganizationTx {
TxType txtype = 1;
uint32 nonce = 2;
optional bytes owner = 3;
optional string name = 4;
optional string infoURI = 5;
repeated bytes managers = 6;
}
```
txType can be one of the following:
+ CREATE_ORGANIZATION: creates a new organization, name is required and cannot be changed anymore. The account creating the organization is set as owner.
+ SET_ORGANIZATION_INFO_URI: sets the infoURI field. Only owner can do it.
+ SET_ORGANIZATION_OWNER: changes the owner (must be different). The new owner account must exist.
+ ADD_ORGANIZATION_MANAGERS: add one or multiple managers
+ DEL_ORGANIZATION_MANAGERS: remove one or multiple managers
+ DEL_ORGANIZATION: removes the organization, only the owner can do it
---
## 5. Inchain census creation and management
Inchain census creation and management would allow for the creation and management of censuses on the Vochain blockchain. This would enable the creation of decentralized, tamper-proof censuses that can be used for voting, identity verification, and other purposes. Organizations would be able to have one or multiple censuses inchain, so anyone can verify the information is correct since this is managed within the Vochain. This can also make the Vochain useful for third party projects, such as OVOTE, to keep a verifiable census available.
A new Census Origin needs to be added to the protocol, this is `ON_CHAIN_TREE_WEIGHTED`.
A new type of transaction needs to be created: `SET_ORGANIZATION_CENSUS`. The transaction can only be sent by managers of the Organization.
```protobuf
message SetOrganizationCensusTx {
TxType txtype = 1;
uint32 nonce = 2;
optional string name = 3;
optional string description 4;
optional Census type = 5; // types supported are ARBO_BLAKE2B and ARBO_POSEIDON
optional bytes censusId = 6;
repeated CensusParticipant accounts = 7;
}
message CensusParticipant {
address bytes 1;
weight string 2;
}
// the censusID indexes the census in the state
// equals to `organizationID[:20]+incrementalNonce[12]`
```
txType can be one of the following:
+ CREATE_CENSUS: adds a new census for the organization. Name, description and type are required. Name and description should have a maximum length of 64 bytes. CensusID is automatically generated by the blockchain logic.
+ DELETE_CENSUS: removes an existing census specified on `censusId`
+ ADD_PARTICIPANTS: adds a list of participant accounts to the blockchain. All participants should exist, else the transaction fails.
If the census Type is POSEIDON, the babyjubjub key is used. Else the account main address is used.
+ DEL_PARTICIPANTS: removes a list of participants from the census.
## 6. Compute results as consensus
Compute results as consensus would allow for the computation of results based on consensus among the nodes on the Vochain blockchain. This would ensure that the results are accurate and tamper-proof, and would also prevent any single node from having too much influence over the outcome. Currently, the results are not part of the state, but by making the Vochain nodes compute and verify the results, the results would be much more verifiable.
To enable this feature, we must introduce a new internal state transition mechanism (IST), which would make the Vochain transition to a new state without the need of external transactions. However all nodes execute the IST at exactly same height. Thus we need to create a new component, part of the state named Internal State Transition Controller (ISTC).
- The IST controller is executed on the blockchain Commit() function, just before saving the state `state.ISTC.Commit(height)`. This method looks for pending executions on this exact height and perform the scheduled actions.
- The controller uses an internal storage (a nostate StateDB space) to save IST peding executions in a persistent manner.
- The execution of the state.NewProcess() schedules a new IST call: `state.ISTC.Schedule(callType, endBlockNumber, id)` where call type is "computeResults" and "endBlockNumber" is the end block for the election and ID is an arbitrary []byte identifier (in this case equals to the processID).
- Meanwhile if there is a Process status change to ENDED (because the organizer of the election decided to end the voting), `state.ISTC.ReSchedule(id, height+1)` is called to re-schedule the results computation for the next block.
- Once the height is reached, the IST call executes "computeResults". The results computation is started in a separated goroutine. In addition a new schedule is trigered to commit the results: `state.ISTC.Schedule("commitResults", height, id)` (id can be nil, then a random id is internaly computed by ISTC).
To calculate the height we must take into account the next formula `height=currentHeight+1 + int(#votesCasted/factor)` where factor is the number of votes required to compute in the time of one block. Thus factor=200 means that the computation of 200 votes per block is expected for all nodes in the network. Increasing this factor would make results commitment faster but would require powerful machines for following the network. With factor=200 (very realistic for supporting small devices) would take around 8 minutes for a 100k size election. This factor should be defined within the genesis file.
- Finally, "commitResults" would store the computed results in the state, thus making the proper state transition (it must be equal for all nodes in order to reach a consensus). Note that commitResults execution must be blocking.
The results are stored in the State Tree, Process subtree (as part of the models.Process value).
## 7. Deprecate Oracle, use validators as keykeepers
To simplify and reduce the number of actors for the network, we might move the keykeeper functionallity (which is creating encryption keys) to the validators. Thus the validators will have the responsability to send and reveal election keys via transaction to the blockchain.
Oracles are not longer needed since any existing account in the blockchain can act as an oracle to create elections on behalf of a third-party network and the results are already computed within the Vochain state.
## Vochain State
The Vochain State is a data structure that is used to store and organize information on the Vocdoni blockchain. It is composed of multiple nested Merkle trees. The MainTree is the root of the Vochain State and its leaf values represent the Merkle root of the nested trees, also known as sub-trees.
One of these sub-trees is the Process tree, which is used to store information about specific elections on the blockchain. Each election is identified by a unique 32-byte processID. Within the Process tree, there are multiple nested Merkle trees that store information related to the election, such as the votes, nullifiers, and other relevant data.
The Merkle tree structure allows for efficient data storage and easy verification of the integrity of the data. Each leaf node in the tree represents a piece of data, and each non-leaf node represents the hash of its child nodes. This creates a tree-like structure where each node is connected to its parent and children, and the root of the tree represents the hash of all the data in the tree.
Because of the Merkle tree structure, it is possible to prove the inclusion or exclusion of a piece of data in the tree without having to reveal the entire tree. This is done by providing a Merkle proof, which is a small set of hashes that can be used to verify the authenticity of a piece of data in the tree.
In the case of the Vocdoni Vochain State, the Merkle tree structure allows for efficient storage and verification of the various data related to the elections on the blockchain. It also allows for privacy and security, as it is possible to prove the authenticity of a piece of data without revealing the entire tree.
This is the current state merkle tree.
```mermaid
graph LR;
subgraph 1st level;
root[[stateRoot]]-.-MainTree
end
subgraph 2nd level;
MainTree[MainTree]-->Extra;
Extra-.-extraInfo{{key:string<br/>val:bytes}}
MainTree-->Oracles;
Oracles-.- oraclesInfo{{key:address<br/>val:1/nil}}
MainTree-->Validators;
Validators-.-validatorsInfo{{key:address<br/>val:models.Validator}}
MainTree-->Accounts;
Accounts-.-accountsInfo{{key:address<br/>val:models.Account}}
MainTree-->Faucet
Faucet-.-faucetInfo{{key:addr+nonce<br/>val:nul}}
MainTree-->Processes;
Processes-.-processesInfo{{key:processID<br>val:models.Process}}
end
subgraph 3rd level;
processesInfo-->PreRegisterCensus-.-prCensusInfo{{key:voterID<br/>val:weight}}
%%processesInfo-->CensusPoseidon;
%%CensusPoseidon-.-censusPoseidonInfo{{key:index<br/>val:pubKey}}
processesInfo-->PreregisterNullifiers;
PreregisterNullifiers-.-nullifiersInfo{{key:initialNullifier<br/>val:weight}}
processesInfo-->Votes;
Votes-.-votesInfo{{key:voteId<br/>val:models.StateDBVote}}
end
MainTree-->Organizations;
Organizations-.- orgsInfo{{key:organizationId<br/>val:models.Organization}}
orgsInfo-->CensusStore;
CensusStore-.-censusStoreInfo{{key:censusId<br/>val:censusRoot}}
censusStoreInfo-->CensusOrg1;
CensusOrg1-.- censusOrgInfo{{key:voterID<br/>val:weight}}
censusStoreInfo-->CensusOrgN;
CensusOrgN-.- censusOrgInfo{{key:voterID<br/>val:weight}}
```