elevenbuckets / OptractContract

Solidity smart contact of https://github.com/elevenbuckets/Optract-Tokenized-Opinions
GNU General Public License v3.0
1 stars 0 forks source link

Block Registry Data Format #7

Open infwonder opened 5 years ago

infwonder commented 5 years ago
  1. sblockNo
  2. ethBlockNo
  3. ethBlockTimestamp?
  4. merkle root
  5. IPFS hash (bytes32)
  6. total unique curated article counts of this OpRound
  7. total unique votes counts of this OpRound
  8. OpRound No. (uint)

===== could have no value unless lottery draw =====

===== could have no value unless OpRound Ended =====

infwonder commented 5 years ago

I wonder how much would the commit gas cost during the most utilized case?

infwonder commented 5 years ago

(i) (ii) (iii) seems to only be needed in one block? If so we need to add a flag so that later block can easily identify if the lottery has been drew already and can easily locate the right block for referencing lottery information.

akaron commented 5 years ago

Hi @infwonder , here are a few questions:

  1. should validator address also in this block registry for dispute purpose? I think there's no need for now since we are the only validators.
  2. Am I understand correctly that (7) unique votes counts means both vote1 (like) and vote2 (claim)? Now I assume both are included.

Right now the block registry data looks like:

    struct blockStat{
        // address validator;
        uint blockHeight;  // block.number while submission
        bytes32 merkleRoot;  // IPFs hash string to bytes32: 
        bytes32 ipfsAddr;  // string to hex (in js): ethUtils.bufferToHex(bs58.decode(ipfsHash).slice(2));
        uint timestamp;
        uint uniqArticleCount;
        uint vote1Count;
        uint vote2Count;
        uint opRound;
        // the following could have no values other than default
        uint lotteryWinningNumber;
        bytes32 lotteryIpfs;
        uint minSuccessRate;  // shoud be an integer between 0 and 100
        bytes32 succesRateDB;  // IPFS contain success rate
        bytes32 finanListIpfs;
    }
    mapping (uint => blockStat) public blockHistory;

and the interface of submitMerkleRoot() looks like

    function submitMerkleRoot(
        bytes32 _merkleRoot,
        bytes32 _ipfsAddr,
        uint _uniqArticleCount,
        uint _vote1Count,
        uint _vote2Count,
        bytes32 _lotteryIpfs,
        uint _minSuccessRate,
        bytes32 _successRateDB,
        bytes32 _finalListIpfs
    ) public validatorOnly returns (bool) {
...
// pseudocode
// if (in OpRound 0 and there are enough accumulated `arcitleCount`):
//      begin OpRound 1 vote phase
// else if (enough vote1 for lottery):
//      determine a `winNumber` here, and save (i)(ii)(iii) provided by validator to chain
// else if (enough vote2):
//      save (iv)(v) provided validator to chain
// else if (just a regular block):
//      only save the basic information

To make sure I understand correctly, here's my understanding of an OpRound:

Just in case, the deployment of current version of OptractContract (commit e16fb05) is in the branch https://github.com/elevenbuckets/OptractContract/tree/deploymentTst , the ABI and artifacts are, as usual, inside dapps/OptractMedia.

infwonder commented 5 years ago

(1) yes, the signature is needed, and we still need it even with only 3 of us as validators!!! (2) No, since vote1 and vote2 (claim) are different stages, we cannot mix them to determine when to trigger lottery.

infwonder commented 5 years ago

opround would at least to have 2 blocks, since we need vote 1 (one block minimal) and vote 2 (one block minimal)

akaron commented 5 years ago

(1) yes -> then there's a new column in the struct (2) I meant to treat them as two set of variables (vote1 and vote1Counts; vote2 and vote2Counts)

And, yes, a OpRound would have at least 2 sblock.

infwonder commented 5 years ago

(1) cool, (2) oh yes! we need to count them separately

akaron commented 5 years ago

updates after today's discussion, I made these changes (already done in commit 6dacb96):

    struct blockStat{
        address validator;
        uint blockHeight;  // block.number while submission
        bytes32 merkleRoot;  // IPFs hash string to bytes32: 
        bytes32 ipfsAddr;  // string to hex (in js): ethUtils.bufferToHex(bs58.decode(ipfsHash).slice(2));
        uint timestamp;
        uint uniqArticleCount;
        uint vote1Count;
        uint vote2Count;
        uint opRound;
        // the following could have no values other than default
        uint lotteryWinningNumber;
        bytes32 lotteryIpfs;
        uint minSuccessRate;  // shoud be an integer between 0 and 100
        bytes32 succesRateDB;  // IPFS contain success rate
        bytes32 finanListIpfs;
    }
    mapping (uint => blockStat) public blockHistory;  // sblockNo to blockStat
    mapping (uint => uint) public lotterySblockNo;  // give `opRound`, return the corresponding `sblock_no`

and the psuedocode:

    function submitMerkleRoot(
        bytes32 _merkleRoot,
        bytes32 _ipfsAddr,
        uint _uniqArticleCount,
        uint _vote1Count,
        uint _vote2Count,
        bytes32 _lotteryIpfs,
        uint _minSuccessRate,
        bytes32 _successRateDB,
        bytes32 _finalListIpfs,
        uint _lotteryWinRange
    ) public validatorOnly returns (bool) {
...
// pseudocode
// if (in OpRound 0 and there are enough accumulated `arcitleCount`):
//      begin OpRound 1 vote phase
// else if (enough vote1 for lottery):
//      determine a `winNumber` here, and save (i)(ii)(iii) provided by validator to chain
// else if (enough vote2):
//      save (iv)(v) provided validator to chain
// else:
//      if (previous sblock is a lottery): save the `_lotteryWinRange` into (i)
//      else: update blockRegistry for a regular block
//      only save the basic information
akaron commented 5 years ago

update in commit 671718f:

The struct:

    struct blockStat{
        address validator;
        uint blockHeight;  // block.number while submission
        bytes32 merkleRoot;  // IPFs hash string to bytes32: 
        bytes32 ipfsAddr;  // string to hex (in js): ethUtils.bufferToHex(bs58.decode(ipfsHash).slice(2));
        uint timestamp;
        uint uniqArticleCount;
        uint vote1Count;
        uint vote2Count;
        bytes32 opRoundId;
        // the following could have no values other than default
        bytes32 lotteryWinNumber;
        bytes32 lotteryIpfs;
        uint minSuccessRate;  // shoud be an integer between 0 and 100
        bytes32 succesRateDB;  // IPFS contain success rate
        bytes32 finanListIpfs;
    }
    mapping (uint => blockStat) public blockHistory;  // sblockNo to blockStat
    mapping (uint => uint) public lotterySblockNo;  // give `opRound`, return the corresponding `sblock_no` while lottery happened
    mapping (uint => bytes32) public opRoundLog;  // opRound index to opRound id

and the submitMerkleRoot pseudo code

    function submitMerkleRoot(
        bytes32 _merkleRoot,
        bytes32 _ipfsAddr,
        uint _uniqArticleCount,
        uint _vote1Count,
        uint _vote2Count,
        bytes32 _lotteryIpfs,
        uint _minSuccessRate,
        bytes32 _successRateDB,
        bytes32 _finalListIpfs
    ) public validatorOnly returns (bool) {

// pseudo code
// if-statement to determine which kind of sblock it is:
// 1. genesis OpRound v1 start 
// 2. vote1 ends normally, lottery time
// 3. vote1 ends as no-draw-round
// 4. vote2 ends normally, finalist generated
// 5. vote2 ends as no-draw-round
// 6. a regular submission
akaron commented 5 years ago

update: since some of the data are their default values while it's not a OpRound Lottery or Finalist block. Thus, some of the blockStat has been moved to a new struct opRoundStruct. There are two advantages: no need to fill so many default values (0/0x0/false) and easier to query OpRound related data (block.height while init and lottery, lotteryWinNumber, ...).

The opRoundStruct and related mappings are (as of commit 317898df):

    struct opRoundStruct{
        // update during creation of this opRound
        bytes32 id;
        uint initBlockNo;
        // update in lottery-sblock
        uint lotteryBlockNo;
        bytes32 lotteryWinNumber;
        // update in final-sblock
        uint8 minSuccessRate;  // shoud be an integer between 0 and 100; this is used in next opRound
        bytes32 succesRateDB;  // IPFS contain success rate
        bytes32 finalListIpfs;
    }
    mapping (uint => opRoundStruct) opRoundHistory;
    mapping (bytes32 => uint) opRoundIdToNum;  // opRound id to opRound number