Using state channels to scale Virtual Pseudonym Parties

in #proofofindividuality7 years ago (edited)

The pseudonym parties last 15 minutes, and Ethereum only does 10-15 transactions per second, roughly 9000 transactions during the pseudonym event. New blockchains like the Parity Polkadot Platform (PPP) plan to include chain fibers, or parachains, making it possible to do parallel processing and potentially millions of transactions per second. Until something like Polkadot is released, one way to scale the POI network could be to use state channels.

Using state-channels, the pseudonym groups could verify one another off-chain (using the point-system with NYM) and sign proofs for the NYM that is given out, and these proofs could then be uploaded to Ethereum, and every user in a group would be able to upload the proofs.

Using these proofs, each nym would know that the points they are given are valid, even tough it would still take potentially days to process the results of the pseudonym parties (86400 seconds in a day, roughly a million transactions per day. )

The period for submitting the proofs would need to be extended from 15 minutes to a few days, making the system a bit more boring to use since there would not be instant gratification after the pseudonym event, whereas using Polkadot the parachains could be hard-coded to only accept transactions for 15 minutes and to then relay only the result to the dApp on the main chain.

Constructing the proofs

Each proof would represent a transaction, and include address nym, int positiveNYM, int negativeNYM, uint sequenceNumber (similar to a nonce but for a state channel), and a hash of the previous NYM proof bytes32 signedProof, and be signed using web3.eth.sign(address, stateProof)

These proofs would be submitted to the Virtual Pseudonym Parties smart-contract, which would check so that each new proof includes a hash of the previous proof, and a sequence number incremented by 1, and verify the signature.

function submitProof(
          uint _chainIndex, 
          uint _groupNumber, 
          address _signer, 
          address _nym, 
          int _positiveNYM, 
          int _negativeNYM, 
          uint _sequenceNumber, 
          bytes32 _signedProof
          ) 
  atTime(pseudonymEvent, issuePOIs)
{
  if(userGroup[_signer] && userGroup[_nym] != _groupNumber) throw;
  bytes32 channelId = pseudonymAddress[_groupNumber];
  uint index = ProofChain[channelId][_chainIndex].length;
  if(index != 0 && _sequenceNumber != ProofChain[channelId][_chainIndex][index].sequenceNumber + 1) throw;
  
  bytes32 previousProof = ProofChain[channelId][_chainIndex][index].signedProof;
  
  bytes32 stateHash = sha3(_nym, _positiveNYM, _negativeNYM, _sequenceNumber, previousProof)

  if(!ecverify(stateHash, _signedProof, _signer)) throw;

  Proof memory newProof = Proof({signer: _signer,
                            nym: _nym,
                            positiveNYM: _positiveNYM,
                            negativeNYM: _negativeNYM,
                            sequenceNumber: _sequenceNumber,
                            signedProof: _signedProof
                          });

  ProofChain[channelId][_chainIndex].push(newProof);
}

To prevent a user from submitting a false proof chain, the smart-contract accepts multiple proofs and then selects the one with the most nym given out.

function getProofNym(uint _chainIndex, uint _groupNumber) atTime(issuePOIs, 0) {
  bytes32 channelId = pseudonymAddress[_groupNumber];
  
  uint totalNym; 
  
/* 
   Calculate total nym in the proof chain, and if 
   it is higher than mostNym[channelId].totalNym, 
   set it as the proof chain with the most nym.
*/

  if(mostNym[channelId] != 0 && mostNym[channelId].totalNym > totalNym) throw;
  mostNym[channelId] = ProofChainNym({chainIndex: _chainIndex, totalNym: totalNym});
}

and then once enough days has passed to process all pseudonym groups, it gives out POIs to the nyms that had more than 4000 points, using the proof chain that had given out the most NYM,

mapping(uint => bool) groupProcessed;

function submitVerifiedUsers(uint _groupNumber, uint _chainIndex) atTime(issuePOIs, 0) {
  if(groupProcessed[_groupNumber] == true) throw;
  bytes32 channelId = pseudonymAddress[_groupNumber];
  if(mostNym[channelId].chainIndex != _chainIndex) throw;
  
  /* (re)calculate the results of the proof chain, then give out POIs to those with more than 4000 points */

      for(uint i = 0; i < pseudonymGroup[_groupNumber].length; i++){
          address nym = pseudonymGroup[_groupNumber][i];
          if(points[nym] >= 4000) POI[nym] = true;
          else depositPenalty(nym);
      }

      groupProcessed[_groupNumber] = true;
}

Conclusion

By constructing proofs using state channels, virtual pseudonym parties running on Ethereum could scale beyond the 9000 transactions per pseudonym event limit (15 minutes, 900 seconds, Ethereum does 10-15 transactions per second. )

A problem would be that off-chain proofs dissolve the boundary for when a pseudonym event ends, since there would no consensus for time stamps of the proofs, and the on-chain contract would accept proofs being submitted for a period of a few days, via function submitProof().

State channels could be used for a proof-of-concept of virtual pseudonym parties, to test the anti-bot deposits and fees, and would later on be replaced with parachains on the Polkadot platform, or something similar.

Smart contract with the examples from this post, https://gist.github.com/resilience-me/c3daf6567af17807d93fe2e365637589

Coin Marketplace

STEEM 0.20
TRX 0.12
JST 0.028
BTC 66490.29
ETH 3513.26
USDT 1.00
SBD 2.54