github.com/codingfuture/orig-energi3@v0.8.4/energi/contracts/test/CheckpointRegistryV2.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 CheckpointRegistryV2 = artifacts.require('CheckpointRegistryV2'); 24 const ICheckpointRegistry = artifacts.require('ICheckpointRegistry'); 25 const ICheckpoint = artifacts.require('ICheckpoint'); 26 const ICheckpointV2 = artifacts.require('ICheckpointV2'); 27 const StorageCheckpointRegistryV1 = artifacts.require('StorageCheckpointRegistryV1'); 28 29 const MasternodeRegistryV1 = artifacts.require('MasternodeRegistryV1'); 30 const MasternodeTokenV1 = artifacts.require('MasternodeTokenV1'); 31 32 const common = require('./common'); 33 const ethjs = require('ethereumjs-util'); 34 35 contract("CheckpointRegistryV2", async accounts => { 36 const s = { 37 artifacts, 38 accounts, 39 assert, 40 it, 41 web3, 42 }; 43 44 before(async () => { 45 s.registry_orig = await MasternodeRegistryV1.deployed(); 46 s.registry = await MasternodeRegistryV1.at(await s.registry_orig.proxy()); 47 48 s.mntoken_orig = await MasternodeTokenV1.deployed(); 49 s.mntoken = await MasternodeTokenV1.at(await s.mntoken_orig.proxy()); 50 51 s.orig = await CheckpointRegistryV2.deployed(); 52 s.proxy = await MockProxy.at(await s.orig.proxy()); 53 s.fake = await MockContract.new(s.proxy.address); 54 s.proxy_abi = await CheckpointRegistryV2.at(s.proxy.address); 55 s.token_abi = await ICheckpointRegistry.at(s.proxy.address); 56 await s.proxy.setImpl(s.orig.address); 57 s.storage = await StorageCheckpointRegistryV1.at(await s.proxy_abi.v1storage()); 58 Object.freeze(s); 59 }); 60 61 after(async () => { 62 const impl = await CheckpointRegistryV2.new( 63 s.proxy.address, s.registry.address, accounts[3]); 64 await s.proxy.setImpl(impl.address); 65 }); 66 67 describe('common pre', () => common.govPreTests(s) ); 68 69 //--- 70 describe('Primary', () => { 71 const { fromAscii, toBN, toWei } = web3.utils; 72 73 const collateral1 = toBN(toWei('50000', 'ether')); 74 const owner1 = accounts[0]; 75 const sigacc = web3.eth.accounts.privateKeyToAccount( 76 '0x4118811427785a33e8c61303e64b43d0d6b69db3caa4074f2ddbdec0b9d4c878'); 77 const mnacc1 = web3.eth.accounts.create(); 78 const nonmnacc1 = web3.eth.accounts.create(); 79 const masternode1 = mnacc1.address; 80 const ip1 = toBN(0x12345678); 81 const enode_common = '123456789012345678901234567890' 82 const enode1 = [fromAscii(enode_common + '11'), fromAscii(enode_common + '11')]; 83 84 const ecsign = (acc, hash) => { 85 const sig = ethjs.ecsign( 86 toBN(hash).toArrayLike(Buffer), 87 toBN(acc.privateKey).toArrayLike(Buffer) 88 ); 89 return '0x'+[sig.r.toString('hex'), sig.s.toString('hex'), sig.v.toString(16)].join(''); 90 }; 91 92 const cp_count = 100; 93 const cp_sign = cp_count - 1; 94 const block_hash = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; 95 let cp_list; 96 let mn_sig; 97 let cpp_sig; 98 99 const mn_sig_reg = async (acc, num, block_hash) => { 100 const sigbase = await s.token_abi.signatureBase(num, block_hash); 101 return ecsign(acc, sigbase); 102 }; 103 const mn_sig_cp = async (acc, cp_address) => { 104 const cp = await ICheckpoint.at(cp_address); 105 const sigbase = await cp.signatureBase(); 106 return ecsign(acc, sigbase); 107 }; 108 109 before(async () => { 110 await s.mntoken.depositCollateral({ 111 from: owner1, 112 value: collateral1, 113 }); 114 await s.registry.announce(masternode1, ip1, enode1, {from: owner1}); 115 }); 116 117 after(async () => { 118 await s.mntoken.withdrawCollateral(collateral1, { 119 from: owner1, 120 }); 121 }); 122 123 it('should refuse propose() with invalid signature length', async () => { 124 try { 125 await s.token_abi.propose(1, block_hash, block_hash); 126 assert.fail('It must fail'); 127 } catch (e) { 128 assert.match(e.message, /Invalid signature length/); 129 } 130 }); 131 132 it('should refuse propose() from invalid signer', async () => { 133 try { 134 await s.token_abi.propose( 135 1, block_hash, await mn_sig_reg(mnacc1, 1, block_hash)); 136 assert.fail('It must fail'); 137 } catch (e) { 138 assert.match(e.message, /Invalid signer/); 139 } 140 }); 141 142 it('should propose() from valid signer', async () => { 143 for (let i = 1; i <= cp_count; ++i) { 144 const num = parseInt(i/2); 145 cpp_sig = await mn_sig_reg(sigacc, num, block_hash); 146 await s.token_abi.propose( 147 num, block_hash, cpp_sig); 148 } 149 }); 150 151 it('should checkpoints()', async () => { 152 cp_list = await s.token_abi.checkpoints(); 153 expect(cp_list.length).equal(cp_count); 154 }); 155 156 it('should refuse to sign() by non-MN', async() => { 157 try { 158 await s.token_abi.sign(cp_list[cp_sign], ecsign(nonmnacc1, block_hash)); 159 assert.fail('It must fail'); 160 } catch (e) { 161 assert.match(e.message, /Not active MN/); 162 } 163 }); 164 165 it('should refuse to sign() by invalid signature length', async() => { 166 try { 167 await s.token_abi.sign(cp_list[cp_sign], block_hash); 168 assert.fail('It must fail'); 169 } catch (e) { 170 assert.match(e.message, /Invalid signature length/); 171 } 172 }); 173 174 it('should sign() by MN', async() => { 175 mn_sig = await mn_sig_cp(mnacc1, cp_list[cp_sign]); 176 await s.token_abi.sign(cp_list[cp_sign], mn_sig); 177 }); 178 179 it('should refuse to sign() by already signed MN', async() => { 180 try { 181 await s.token_abi.sign(cp_list[cp_sign], await mn_sig_cp(mnacc1, cp_list[cp_sign])); 182 assert.fail('It must fail'); 183 } catch (e) { 184 assert.match(e.message, /Already signed/); 185 } 186 }); 187 188 it('should refuse to sign() by CPP signer', async() => { 189 try { 190 await s.token_abi.sign(cp_list[cp_sign], await mn_sig_cp(sigacc, cp_list[cp_sign])); 191 assert.fail('It must fail'); 192 } catch (e) { 193 assert.match(e.message, /Already signed/); 194 } 195 }); 196 197 it('should have correct signatureBase()', async () => { 198 const hash = await s.token_abi.signatureBase(cp_sign+1, block_hash); 199 const reqhash = web3.utils.soliditySha3( 200 "||Energi Blockchain Checkpoint||", 201 toBN(cp_sign + 1), 202 toBN(block_hash), 203 ); 204 expect(hash.toString()).equal(reqhash.toString()); 205 }); 206 207 describe('CheckpointV2', async () => { 208 it('should show info()', async () => { 209 const cp = await ICheckpoint.at(cp_list[cp_sign]); 210 const res = await cp.info(); 211 212 common.stringifyBN(web3, res); 213 expect(res).include({ 214 number: toBN(parseInt((cp_sign+1)/2)).toString(), 215 hash: block_hash, 216 }); 217 expect(res).include.keys('since'); 218 }); 219 220 it('should show signature()', async () => { 221 const cp = await ICheckpoint.at(cp_list[cp_sign]); 222 const res = await cp.signature(masternode1); 223 224 expect(res.toString()).equal(mn_sig); 225 }); 226 227 it('should show signature() of CPP signer', async () => { 228 const cp = await ICheckpoint.at(cp_list[cp_sign]); 229 const res = await cp.signature(sigacc.address); 230 231 expect(res.toString()).equal(cpp_sig); 232 }); 233 234 it('should fail signature() on not signed', async () => { 235 const cp = await ICheckpoint.at(cp_list[cp_sign]); 236 237 try { 238 await cp.signature(accounts[0]); 239 assert.fail('It must fail'); 240 } catch (e) { 241 assert.match(e.message, /Not signed yet/); 242 } 243 }); 244 245 it('should show signatures()', async () => { 246 const cp = await ICheckpoint.at(cp_list[cp_sign]); 247 const res = await cp.signatures(); 248 249 expect(res).include(cpp_sig); 250 expect(res).include(mn_sig); 251 }); 252 253 it('should have correct signatureBase()', async () => { 254 const cp = await ICheckpoint.at(cp_list[cp_sign]); 255 const hash = await cp.signatureBase(); 256 const reqhash = web3.utils.soliditySha3( 257 "||Energi Blockchain Checkpoint||", 258 toBN(parseInt((cp_sign+1)/2)), 259 toBN(block_hash), 260 ); 261 expect(hash.toString()).equal(reqhash.toString()); 262 }); 263 264 it('should correctly handle canVote()', async () => { 265 const num = 101; 266 await s.token_abi.propose(num, block_hash, 267 await mn_sig_reg(sigacc, num, block_hash)); 268 const cps = await s.token_abi.checkpoints(); 269 const cpa = cps[cps.length - 1]; 270 const cp = await ICheckpointV2.at(cpa); 271 272 expect(await cp.canVote(sigacc.address)).false; 273 274 expect(await cp.canVote(masternode1)).true; 275 await s.token_abi.sign(cpa, await mn_sig_cp(mnacc1, cpa)); 276 expect(await cp.canVote(masternode1)).false; 277 278 expect(await cp.canVote(nonmnacc1.address)).true; 279 280 for (let i = 0; i < 24*60-1; ++i) { 281 try { 282 expect(await cp.canVote(nonmnacc1.address)).true; 283 } catch (e) { 284 // eslint-disable-next-line no-console 285 console.log(`Iteration ${i}`); 286 throw e; 287 } 288 common.moveTime(web3, 1); 289 } 290 291 expect(await cp.canVote(nonmnacc1.address)).false; 292 }); 293 }); 294 }); 295 296 //--- 297 describe('StorageCheckpointRegistryV1', async () => { 298 it ('should refuse add() from outside', async () => { 299 try { 300 await s.storage.add(s.fake.address); 301 assert.fail('It must fail'); 302 } catch (e) { 303 assert.match(e.message, /Not owner/); 304 } 305 }); 306 307 it ('should listCheckpoints() from outside', async () => { 308 await s.storage.listCheckpoints(); 309 }); 310 }); 311 312 //--- 313 describe('common post', () => common.govPostTests(s) ); 314 });