github.com/codingfuture/orig-energi3@v0.8.4/energi/contracts/test/CheckpointRegistryV1.spec.js (about)

     1  // Copyright 2019 The Energi Core Authors
     2  // This file is part of the Energi Core library.
     3  //
     4  // The Energi Core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Energi Core library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Energi Governance system is the fundamental part of Energi Core.
    18  
    19  'use strict';
    20  
    21  const MockProxy = artifacts.require('MockProxy');
    22  const MockContract = artifacts.require('MockContract');
    23  const CheckpointRegistryV1 = artifacts.require('CheckpointRegistryV1');
    24  const ICheckpointRegistry = artifacts.require('ICheckpointRegistry');
    25  const ICheckpoint = artifacts.require('ICheckpoint');
    26  const StorageCheckpointRegistryV1 = artifacts.require('StorageCheckpointRegistryV1');
    27  
    28  const MasternodeRegistryV1 = artifacts.require('MasternodeRegistryV1');
    29  const MasternodeTokenV1 = artifacts.require('MasternodeTokenV1');
    30  
    31  const common = require('./common');
    32  const ethjs = require('ethereumjs-util');
    33  
    34  contract("CheckpointRegistryV1", async accounts => {
    35      const s = {
    36          artifacts,
    37          accounts,
    38          assert,
    39          it,
    40          web3,
    41      };
    42  
    43      before(async () => {
    44          s.registry_orig = await MasternodeRegistryV1.deployed();
    45          s.registry = await MasternodeRegistryV1.at(await s.registry_orig.proxy());
    46  
    47          s.mntoken_orig = await MasternodeTokenV1.deployed();
    48          s.mntoken = await MasternodeTokenV1.at(await s.mntoken_orig.proxy());
    49  
    50          s.orig = await CheckpointRegistryV1.deployed();
    51          s.proxy = await MockProxy.at(await s.orig.proxy());
    52          s.fake = await MockContract.new(s.proxy.address);
    53          s.proxy_abi = await CheckpointRegistryV1.at(s.proxy.address);
    54          s.token_abi = await ICheckpointRegistry.at(s.proxy.address);
    55          await s.proxy.setImpl(s.orig.address);
    56          s.storage = await StorageCheckpointRegistryV1.at(await s.proxy_abi.v1storage());
    57          Object.freeze(s);
    58      });
    59  
    60      after(async () => {
    61          const impl = await CheckpointRegistryV1.new(
    62              s.proxy.address, s.registry.address, accounts[3]);
    63          await s.proxy.setImpl(impl.address);
    64      });
    65  
    66      describe('common pre', () => common.govPreTests(s) );
    67  
    68      //---
    69      describe('Primary', () => {
    70          const { fromAscii, toBN, toWei } = web3.utils;
    71  
    72          const collateral1 = toBN(toWei('50000', 'ether'));
    73          const owner1 = accounts[0];
    74          const sigacc = web3.eth.accounts.privateKeyToAccount(
    75              '0x4118811427785a33e8c61303e64b43d0d6b69db3caa4074f2ddbdec0b9d4c878');
    76          const mnacc1 = web3.eth.accounts.create();
    77          const nonmnacc1 = web3.eth.accounts.create();
    78          const masternode1 = mnacc1.address;
    79          const ip1 = toBN(0x12345678);
    80          const enode_common = '123456789012345678901234567890'
    81          const enode1 = [fromAscii(enode_common + '11'), fromAscii(enode_common + '11')];
    82  
    83          const ecsign = (acc, hash) => {
    84              const sig = ethjs.ecsign(
    85                  toBN(hash).toArrayLike(Buffer),
    86                  toBN(acc.privateKey).toArrayLike(Buffer)
    87              );
    88              return '0x'+[sig.r.toString('hex'), sig.s.toString('hex'), sig.v.toString(16)].join('');
    89          };
    90      
    91          const cp_count = 100;
    92          const cp_sign = cp_count - 1;
    93          const block_hash = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
    94          let cp_list;
    95          let mn_sig;
    96  
    97          const mn_sig_reg = async (acc, num, block_hash) => {
    98              const sigbase = await s.token_abi.signatureBase(num, block_hash); 
    99              return ecsign(acc, sigbase);
   100          };
   101          const mn_sig_cp = async (acc, cp_address) => {
   102              const cp = await ICheckpoint.at(cp_address);
   103              const sigbase = await cp.signatureBase();
   104              return ecsign(acc, sigbase);
   105          };
   106  
   107          before(async () => {
   108              await s.mntoken.depositCollateral({
   109                  from: owner1,
   110                  value: collateral1,
   111              });
   112              await s.registry.announce(masternode1, ip1, enode1, {from: owner1});
   113          });
   114  
   115          after(async () => {
   116              await s.mntoken.withdrawCollateral(collateral1, {
   117                  from: owner1,
   118              });
   119          });
   120  
   121          it('should refuse propose() with invalid signature length', async () => {
   122              try {
   123                  await s.token_abi.propose(1, block_hash, block_hash);
   124                  assert.fail('It must fail');
   125              } catch (e) {
   126                  assert.match(e.message, /Invalid signature length/);
   127              }
   128          });
   129  
   130          it('should refuse propose() from invalid signer', async () => {
   131              try {
   132                  await s.token_abi.propose(
   133                      1, block_hash, await mn_sig_reg(mnacc1, 1, block_hash));
   134                  assert.fail('It must fail');
   135              } catch (e) {
   136                  assert.match(e.message, /Invalid signer/);
   137              }
   138          });
   139  
   140          it('should propose() from valid signer', async () => {
   141              for (let i = 1; i <= cp_count; ++i) {
   142                  const num = parseInt(i/2);
   143                  await s.token_abi.propose(
   144                      num, block_hash,
   145                      await mn_sig_reg(sigacc, num, block_hash));
   146              }
   147          });
   148  
   149          it('should checkpoints()', async () => {
   150              cp_list = await s.token_abi.checkpoints();
   151              expect(cp_list.length).equal(cp_count);
   152          });
   153  
   154          it('should refuse to sign() by non-MN', async() => {
   155              try {
   156                  await s.token_abi.sign(cp_list[cp_sign], ecsign(nonmnacc1, block_hash));
   157                  assert.fail('It must fail');
   158              } catch (e) {
   159                  assert.match(e.message, /Not active MN/);
   160              }
   161          });
   162          
   163          it('should refuse to sign() by invalid signature length', async() => {
   164              try {
   165                  await s.token_abi.sign(cp_list[cp_sign], block_hash);
   166                  assert.fail('It must fail');
   167              } catch (e) {
   168                  assert.match(e.message, /Invalid signature length/);
   169              }
   170          });
   171  
   172          it('should sign() by MN', async() => {
   173              mn_sig = await mn_sig_cp(mnacc1, cp_list[cp_sign]);
   174              await s.token_abi.sign(cp_list[cp_sign], mn_sig);
   175          });
   176  
   177          it('should refuse to sign() by already signed MN', async() => {
   178              try {
   179                  await s.token_abi.sign(cp_list[cp_sign], await mn_sig_cp(mnacc1, cp_list[cp_sign]));
   180                  assert.fail('It must fail');
   181              } catch (e) {
   182                  assert.match(e.message, /Already signed/);
   183              }
   184          });
   185  
   186          it('should have correct signatureBase()', async () => {
   187              const hash = await s.token_abi.signatureBase(cp_sign+1, block_hash);
   188              const reqhash = web3.utils.soliditySha3(
   189                  "||Energi Blockchain Checkpoint||",
   190                  toBN(cp_sign + 1),
   191                  toBN(block_hash),
   192              );
   193              expect(hash.toString()).equal(reqhash.toString());
   194          });
   195  
   196          describe('CheckpointV1', async () => {
   197              it('should show info()', async () => {
   198                  const cp = await ICheckpoint.at(cp_list[cp_sign]);
   199                  const res = await cp.info();
   200  
   201                  common.stringifyBN(web3, res);
   202                  expect(res).include({
   203                      number: toBN(parseInt((cp_sign+1)/2)).toString(),
   204                      hash:   block_hash,
   205                  });
   206                  expect(res).include.keys('since');
   207              });
   208  
   209              it('should show signature()', async () => {
   210                  const cp = await ICheckpoint.at(cp_list[cp_sign]);
   211                  const res = await cp.signature(masternode1);
   212  
   213                  expect(res.toString()).equal(mn_sig);
   214              });
   215  
   216              it('should fail signature() on not signed', async () => {
   217                  const cp = await ICheckpoint.at(cp_list[cp_sign]);
   218  
   219                  try {
   220                      await cp.signature(accounts[0]);
   221                      assert.fail('It must fail');
   222                  } catch (e) {
   223                      assert.match(e.message, /Not signed yet/);
   224                  }
   225              });
   226  
   227              it('should show signatures()', async () => {
   228                  const cp = await ICheckpoint.at(cp_list[cp_sign]);
   229                  const res = await cp.signatures();
   230  
   231                  expect(res).include(mn_sig);
   232              });
   233  
   234              it('should have correct signatureBase()', async () => {
   235                  const cp = await ICheckpoint.at(cp_list[cp_sign]);
   236                  const hash = await cp.signatureBase();
   237                  const reqhash = web3.utils.soliditySha3(
   238                      "||Energi Blockchain Checkpoint||",
   239                      toBN(parseInt((cp_sign+1)/2)),
   240                      toBN(block_hash),
   241                  );
   242                  expect(hash.toString()).equal(reqhash.toString());
   243              });
   244          });
   245      });
   246  
   247      //---
   248      describe('StorageCheckpointRegistryV1', async () => {
   249          it ('should refuse add() from outside', async () => {
   250              try {
   251                  await s.storage.add(s.fake.address);
   252                  assert.fail('It must fail');
   253              } catch (e) {
   254                  assert.match(e.message, /Not owner/);
   255              }
   256          });
   257  
   258          it ('should listCheckpoints() from outside', async () => {
   259              await s.storage.listCheckpoints();
   260          });
   261      });
   262  
   263      //---
   264      describe('common post', () => common.govPostTests(s) );
   265  });