Search code examples
blockchainethereumistanbulsolidityquorum

What contract is used in Istanbul consensus mechanism in JP Morgan Quorum?


In "7nodes" installation example from JPMorgan Quorum github is used such a genesis file ("istanbul-genesus.json"):

{
"alloc": {
  "0x0000000000000000000000000000000000000020": {
    "code": "0x606060405236156100c45760e060020a60003504631290948581146100c9578063284d163c146100f957806342169e4814610130578063488099a6146101395780634fe437d514610154578063559c390c1461015d57806368bb8bb61461025d57806372a571fc146102c857806386c1ff681461036957806398ba676d146103a0578063a7771ee31461040b578063adfaa72e14610433578063cf5289851461044e578063de8fa43114610457578063e814d1c71461046d578063f4ab9adf14610494575b610002565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c45760018190555b50565b610548600435600160a060020a03331660009081526005602052604090205460ff16156100c4576004546001141561055e57610002565b61045b60025481565b61054a60043560056020526000908152604090205460ff1681565b61045b60015481565b61045b60043560006000600060006000600050600186038154811015610002579080526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630192505b60018301548110156105d75760018301805484916000918490811015610002576000918252602080832090910154835282810193909352604091820181205485825292869052205410801561023257506001805490840180548591600091859081101561000257906000526020600020900160005054815260208101919091526040016000205410155b156102555760018301805482908110156100025760009182526020909120015491505b6001016101a8565b610548600435602435600160a060020a03331660009081526003602052604081205460ff16156100c4578054839010156105e45780548084038101808355908290829080158290116105df576002028160020283600052602060002091820191016105df919061066b565b610548600435600160a060020a03331660009081526005602052604090205460ff16156100c457600160a060020a0381166000908152604090205460ff1615156100f65760406000819020805460ff191660019081179091556004805490910190558051600160a060020a038316815290517f1a4ce6942f7aa91856332e618fc90159f13a340611a308f5d7327ba0707e56859181900360200190a16100f6565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c4576002546001141561071457610002565b61045b600435602435600060006000600050600185038154811015610002579080526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630181509050806001016000508381548110156100025750825250602090200154919050565b61054a600435600160a060020a03811660009081526003602052604090205460ff165b919050565b61054a60043560036020526000908152604090205460ff1681565b61045b60045481565b6000545b60408051918252519081900360200190f35b61054a600435600160a060020a03811660009081526005602052604090205460ff1661042e565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c457600160a060020a03811660009081526003602052604090205460ff1615156100f65760406000818120600160a060020a0384169182905260036020908152815460ff1916600190811790925560028054909201909155825191825291517f0ad2eca75347acd5160276fe4b5dad46987e4ff4af9e574195e3e9bc15d7e0ff929181900390910190a16100f6565b005b604080519115158252519081900360200190f35b600160a060020a03811660009081526005602052604090205460ff16156100f65760406000819020805460ff19169055600480546000190190558051600160a060020a038316815290517f8cee3054364d6799f1c8962580ad61273d9d38ca1ff26516bd1ad23c099a60229181900360200190a16100f6565b509392505050565b505050505b60008054600019850190811015610002578382526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563016020819052604082205490925014156106b8578060010160005080548060010182818154818355818115116106a5578183600052602060002091820191016106a5919061068d565b50506002015b808211156106a157600181018054600080835591825260208220610665918101905b808211156106a1576000815560010161068d565b5090565b5050506000928352506020909120018290555b600082815260208281526040918290208054600101905581514381529081018490528151600160a060020a033316927f3d03ba7f4b5227cdb385f2610906e5bcee147171603ec40005b30915ad20e258928290030190a2505050565b600160a060020a03811660009081526003602052604090205460ff16156100f65760406000819020805460ff19169055600280546000190190558051600160a060020a038316815290517f183393fc5cffbfc7d03d623966b85f76b9430f42d3aada2ac3f3deabc78899e89181900360200190a16100f656",
    "storage": {
      "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02",

      "0x0000000000000000000000000000000000000000000000000000000000000002": "0x03",
      "0x29ecdbdf95c7f6ceec92d6150c697aa14abeb0f8595dd58d808842ea237d8494": "0x01",
      "0x6aa118c6537572d8b515a9f9154be55a3377a8de7991cd23bf6e5ceb368688e3": "0x01",
      "0x50793743212c6f01d326957d7069005b912f8215f10c7536be6b10782c6c44cd": "0x01",

      "0x0000000000000000000000000000000000000000000000000000000000000004": "0x02",
      "0xaca3b76ed4968740c3180dd7fa37f4aa229a2c758a848f53920e9ccb4c4bb74e": "0x01",
      "0xd188ba2dc293670542c1befaf7678b0859e5354a0727d1188b2afb6f47fe24d1": "0x01"
    },
    "balance": "1000000000000000000000000000"
  },

  "0xed9d02e382b34818e88b88a309c7fe71e65f419d": {
    "balance": "1000000000000000000000000000"
  },
  "0xca843569e3427144cead5e4d5999a3d0ccf92b8e": {
    "balance": "1000000000000000000000000000"
  },
  "0x0fbdc686b912d7722dc86510934589e0aaf3b55a": {
    "balance": "1000000000000000000000000000"
  },
  "0x9186eb3d20cbd1f5f992a950d808c4495153abd5": {
    "balance": "1000000000000000000000000000"
  },
  "0x0638e1574728b6d862dd5d3a3e0942c3be47d996": {
    "balance": "1000000000000000000000000000"
  }
},
"coinbase": "0x0000000000000000000000000000000000000000",
"config": {
  "homesteadBlock": 1,
    "eip150Block": 2,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 3,
    "eip158Block": 3,
  "istanbul": {
    "epoch": 30000,
    "policy": 0
  },
  "isQuorum": true
},
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f897f893946571d97f340c8495b661a823f2c2145ca47d63c2948157d4437104e3b8df4451a85f7b2438ef6699ff94b131288f355bc27090e542ae0be213c20350b76794b912de287f9b047b4228436e94b5b78e3ee1617194d8dba507e85f116b1f7e231ca8525fc9008a696694e36cbeb565b061217930767886474e3cde903ac594f512a992f3fb749857d758ffda1330e590fa915e80c0",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"nonce": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"

}

So, this genesis file, obviously, contains contract binary code at address 0x00...0020.

But what is the source code of this contract?

I have read, that in old versions of Quorum this contract was the voting contract of QuorumChain consensus algorithm. In latest version they removed QuorumChain and added Istanbul BFT consensus. So it is new contract.

And you can not find its source code in the Quorum sources. There are no contracts similar to this one (even by size) in the sources.

I decompiled this contract in EVM mnemocode, but original sources will be more helpfull.

P.S.

I asked for this question Quorum team (by their contact email) - they didn't respond.


Solution

  • Possibly, it is block_voting.sol. I'm 90% sure.

    Also, I'm 90% sure that it's garbage. This contract is not used by Istanbul consensus.

    Some evidence (with radare2):

    1. Cut "code:" content from "istanbul-genesus.json", and paste to text file "istanbul-cintract.hex". Remove "0x" prefix: "606060405236156100c45760e060020a6...

    2. Transform it to binary by "rax2" tool:

      $ rax2 -s < ./istanbul-cintract.hex > ./istanbul-cintract.bin
      
    3. Disassemble it with "radare2" (install "evm" architecture package if not installed, $ r2pm install evm). Useful links is Debugging EVM and Reversing EVM.

      $ r2 -A -a evm ./istanbul-cintract.bin
        Cannot set bits 64 to 'evm'
        Cannot set bits 64 to 'evm'
        -- some kind of jokes form radare2 here... dont panic
        [0x00000000]> pdf > ./istanbul-cintract.asm
      
    4. Now you got "istanbul-cintract.asm". Some analysis of it:

      0x00000014 6312909485 push4 0x12909485 ; it is "SELECTOR" of public function
                                        ; S:[0x12909485, FUNC_SELECTOR]  //FUNC_SELECTOR - first 4 byte of transaction data
      0x00000019 81         dup2        ; S:[FUNC_SELECTOR, 0x12909485, FUNC_SELECTOR]
      0x0000001a 14         eq          ; S:[(FUNC_SELECTOR == 0x12909485), FUNC_SELECTOR]
      0x0000001b 6100c9     push2 0xc9  ; S:[0xc9, (FUNC_SELECTOR == 0x12909485), FUNC_SELECTOR]
      0x0000001e 57         jumpi       ; if (FUNC_SELECTOR == 0x12909485) goto 0xc9 address of bytecode
      
    5. This is a public interface function call. If function selector (the first 4 bytes of transaction data) is 0x12909485, it jumps on function body. Below in the text we can find the remaining selectors of public functions:

      0x00000014 6312909485  push4 0x12909485 
      ... etc, only selector push commands...
      0x00000020 63284d163c  push4 0x284d163c
      0x0000002b 6342169e48  push4 0x42169e48
      0x00000036 63488099a6  push4 0x488099a6
      0x00000041 634fe437d5  push4 0x4fe437d5
      0x0000004c 63559c390c  push4 0x559c390c
      0x00000057 6368bb8bb6  push4 0x68bb8bb6
      0x00000062 6372a571fc  push4 0x72a571fc
      0x0000006d 6386c1ff68  push4 0x86c1ff68
      0x00000078 6398ba676d  push4 0x98ba676d
      0x00000083 63a7771ee3  push4 0xa7771ee3
      0x0000008e 63adfaa72e  push4 0xadfaa72e
      0x00000099 63cf528985  push4 0xcf528985
      0x000000a4 63de8fa431  push4 0xde8fa431
      0x000000af 63e814d1c7  push4 0xe814d1c7
      0x000000ba 63f4ab9adf  push4 0xf4ab9adf
      
    6. As the final proof that this bytecode has the same interface as block_voting.sol let recalculate selectors by signatures from the "block_voting.sol" and compare with found ones in bytecode:

      0x12909485 == web3.sha3("setVoteThreshold(uint256)").substr(0,10)
      0x284d163c == web3.sha3("removeBlockMaker(address)").substr(0,10);
      0x42169e48 == web3.sha3("voterCount()").substr(0,10);
      0x488099a6 == web3.sha3("canCreateBlocks(address)").substr(0,10);
      0x4fe437d5 == web3.sha3("voteThreshold()").substr(0,10);
      0x559c390c == web3.sha3("getCanonHash(uint256)").substr(0,10);
      0x68bb8bb6 == web3.sha3("vote(uint256,bytes32)").substr(0,10);
      0x72a571fc == ??? not found...
      0x86c1ff68 == web3.sha3("removeVoter(address)").substr(0,10);
      0x98ba676d == web3.sha3("getEntry(uint256,uint256)").substr(0,10);
      0xa7771ee3 == web3.sha3("isVoter(address)").substr(0,10);
      0xadfaa72e == web3.sha3("canVote(address)").substr(0,10);
      0xcf528985 == web3.sha3("blockMakerCount()").substr(0,10);
      0xde8fa431 == web3.sha3("getSize()").substr(0,10);
      0xe814d1c7 == web3.sha3("isBlockMaker(address)").substr(0,10);
      0xf4ab9adf == web3.sha3("addVoter(address)").substr(0,10);
      

    It is for you to decide what is this...