github.com/codingfuture/orig-energi3@v0.8.4/energi/contracts/test/MasternodeRegistryV2.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 MockProposal = artifacts.require('MockProposal'); 24 const MockSporkRegistry = artifacts.require('MockSporkRegistry') 25 const MockMasternodeTokenV2 = artifacts.require('MockMasternodeTokenV2') 26 const MasternodeRegistryV2 = artifacts.require('MasternodeRegistryV2'); 27 const MasternodeRegistryV1 = artifacts.require('MasternodeRegistryV1'); 28 const IBlockReward = artifacts.require('IBlockReward'); 29 const IMasternodeRegistryV2 = artifacts.require('IMasternodeRegistryV2'); 30 const IMasternodeToken = artifacts.require('IMasternodeToken'); 31 const ITreasury = artifacts.require('ITreasury'); 32 const StorageMasternodeRegistryV1 = artifacts.require('StorageMasternodeRegistryV1'); 33 34 const common = require('./common'); 35 36 contract("MasternodeRegistryV2", async accounts => { 37 const s = { 38 artifacts, 39 accounts, 40 assert, 41 it, 42 web3, 43 storage: null, 44 }; 45 46 const { toWei } = web3.utils; 47 const vperiod = common.mnregistry_config_v2[1]; 48 const isTargetChanges = async (_token, _mn) => { 49 return await _token.validationTarget(_mn, 'latest') != await _token.validationTarget(_mn, 'pending'); 50 }; 51 const sw_features = web3.utils.toBN((1 << 24) | (2 << 16) | (3 << 8)); 52 53 before(async () => { 54 s.orig = await MasternodeRegistryV2.deployed(); 55 s.proxy = await MockProxy.at(await s.orig.proxy()); 56 await s.proxy.setImpl(s.orig.address); 57 58 s.fake = await MockContract.new(s.proxy.address); 59 s.proxy_abi = await MasternodeRegistryV2.at(s.proxy.address); 60 61 s.token_abi = await IMasternodeRegistryV2.at(s.proxy.address); 62 s.reward_abi = await IBlockReward.at(s.proxy.address); 63 s.storage = await StorageMasternodeRegistryV1.at(await s.proxy_abi.v1storage()); 64 65 s.mntoken_proxy_addr = await s.orig.token_proxy(); 66 //s.mntoken_proxy = await MockProxy.at(s.mntoken_proxy_addr); 67 s.mntoken_abi = await IMasternodeToken.at(s.mntoken_proxy_addr); 68 69 s.treasury_proxy_addr = await s.orig.treasury_proxy(); 70 s.treasury_proxy = await MockProxy.at(s.treasury_proxy_addr); 71 s.treasury_abi = await ITreasury.at(s.treasury_proxy_addr); 72 s.treasury_impl = await ITreasury.at(await s.treasury_proxy.impl()); 73 74 Object.freeze(s); 75 }); 76 77 after(async () => { 78 const impl = await MasternodeRegistryV2.new( 79 s.proxy.address, 80 s.mntoken_proxy_addr, 81 s.treasury_proxy_addr, 82 common.mnregistry_config_v2, 83 common.mnreg_deploy_opts 84 ); 85 await s.proxy.setImpl(impl.address); 86 }); 87 88 describe('common pre', () => common.govPreTests(s) ); 89 90 //--- 91 describe('Primary', () => { 92 const { fromAscii, toBN } = web3.utils; 93 94 const collateral1 = toWei('3000', 'ether'); 95 const collateral2 = toWei('2000', 'ether'); 96 const collateral3 = toWei('1000', 'ether'); 97 const reward = toBN(toWei('9.14', 'ether')); 98 99 const owner1 = accounts[1]; 100 const owner2 = accounts[2]; 101 const owner3 = accounts[3]; 102 const not_owner = accounts[0]; 103 104 const masternode1 = accounts[9]; 105 const masternode2 = accounts[8]; 106 const masternode3 = accounts[7]; 107 108 const ip1 = toBN(0x12345678); 109 const ip2 = toBN(0x87654321); 110 const ip3 = toBN(0x43218765); 111 112 const enode_common = '123456789012345678901234567890' 113 const enode1 = [fromAscii(enode_common + '11'), fromAscii(enode_common + '11')]; 114 const enode2 = [fromAscii(enode_common + '11'), fromAscii(enode_common + '22')]; 115 const enode3 = [fromAscii(enode_common + '11'), fromAscii(enode_common + '33')]; 116 117 before(async () => { 118 await s.mntoken_abi.depositCollateral({ 119 from: owner1, 120 value: collateral1, 121 }); 122 await s.mntoken_abi.depositCollateral({ 123 from: owner2, 124 value: collateral2, 125 }); 126 await s.mntoken_abi.depositCollateral({ 127 from: owner3, 128 value: collateral3, 129 }); 130 }); 131 132 after(async () => { 133 await s.mntoken_abi.withdrawCollateral(collateral1, { 134 from: owner1, 135 }); 136 await s.mntoken_abi.withdrawCollateral(collateral2, { 137 from: owner2, 138 }); 139 await s.mntoken_abi.withdrawCollateral(collateral3, { 140 from: owner3, 141 }); 142 }); 143 144 const checkHeartbeat = async () => { 145 try { 146 const evt = await s.orig.getPastEvents('Heartbeat', common.evt_last_block); 147 expect(evt).lengthOf(0); 148 } catch(e) { 149 //expect(e.message).match(/doesn't exist in this contract/); 150 } 151 }; 152 153 describe('No MN', () => { 154 it('should silently denounce()', async () => { 155 await s.token_abi.denounce(masternode1); 156 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(0); 157 }); 158 159 it('should refuse to heartbeat() too old block', async () => { 160 const bn = await web3.eth.getBlockNumber(); 161 const b = await web3.eth.getBlock(bn); 162 163 try { 164 await s.token_abi.heartbeat(bn - 11, b.hash, sw_features, common.zerofee_callopts); 165 assert.fail('It should fail'); 166 } catch(e) { 167 assert.match(e.message, /Too old/); 168 } 169 }); 170 171 it('should refuse to heartbeat() wrong block', async () => { 172 const bn = (await web3.eth.getBlockNumber()); 173 const b = await web3.eth.getBlock(bn); 174 175 try { 176 await s.token_abi.heartbeat(bn - 10, b.hash, sw_features, common.zerofee_callopts); 177 assert.fail('It should fail'); 178 } catch(e) { 179 assert.match(e.message, /Block mismatch/); 180 } 181 }); 182 183 it('should refuse to heartbeat() not active', async () => { 184 const bn = await web3.eth.getBlockNumber(); 185 const b = await web3.eth.getBlock(bn); 186 187 try { 188 await s.token_abi.heartbeat(bn, b.hash, sw_features, common.zerofee_callopts); 189 assert.fail('It should fail'); 190 } catch(e) { 191 assert.match(e.message, /Not active/); 192 } 193 }); 194 195 it('should refuse to invalidate() vote for self', async () => { 196 try { 197 await s.token_abi.invalidate( 198 owner1, {from: owner1, ...common.zerofee_callopts}); 199 assert.fail('It should fail'); 200 } catch(e) { 201 assert.match(e.message, /Invalidation for self/); 202 } 203 }); 204 205 it('should refuse to invalidate() not active', async () => { 206 try { 207 await s.token_abi.invalidate(masternode2, common.zerofee_callopts); 208 assert.fail('It should fail'); 209 } catch(e) { 210 assert.match(e.message, /Not active caller/); 211 } 212 }); 213 214 it('should not be isActive()', async () => { 215 const res = await s.token_abi.isActive(masternode1); 216 expect(res).false; 217 }); 218 219 it('should correctly count()', async () => { 220 const res = await s.token_abi.count(); 221 assert.equal(res[0], 0); 222 assert.equal(res[1], 0); 223 assert.equal(res[2], 0); 224 }); 225 226 it('should handle info()', async () => { 227 try { 228 await s.token_abi.info(masternode1); 229 assert.fail('It should fail'); 230 } catch (e) { 231 assert.match(e.message, /Unknown masternode/); 232 } 233 }); 234 235 it('should handle ownerInfo()', async () => { 236 try { 237 await s.token_abi.ownerInfo(owner1); 238 assert.fail('It should fail'); 239 } catch (e) { 240 assert.match(e.message, /Unknown owner/); 241 } 242 }); 243 244 it('should process reward() to Treasury', async () => { 245 const treasury_before = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 246 247 let r = await s.reward_abi.getReward(0); 248 assert.equal(r.valueOf(), 0); 249 250 const count = 3; 251 252 for (let i = count; i > 0; --i) { 253 r = await s.reward_abi.getReward(i); 254 255 if (r.eq(toBN(0))) { 256 // superblock case 257 r = await s.reward_abi.getReward(i+1); 258 } 259 260 expect(r.toString()).eql(reward.toString()); 261 await s.reward_abi.reward({ 262 from: not_owner, 263 value: r 264 }); 265 } 266 267 // Kick the rest 268 await s.reward_abi.reward(); 269 270 const treasury_after = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 271 expect(treasury_after.sub(treasury_before).toString()) 272 .eql(reward.mul(toBN(count)).toString()); 273 }); 274 275 it('should handle onCollateralUpdate()', async () => { 276 await s.token_abi.onCollateralUpdate(owner1); 277 }); 278 279 it('collateralLimits() should return correct values', async () => { 280 let limits = await s.token_abi.collateralLimits(); 281 common.stringifyBN(web3, limits); 282 expect(limits).include({ 283 min: '1000000000000000000000', // 1000 NRG 284 max: '100000000000000000000000', // 100,000 NRG 285 }); 286 }); 287 288 it('should handle enumerate()', async () => { 289 expect(await s.token_abi.enumerate()).lengthOf(0); 290 }); 291 292 it.skip('must forbid more than one reward() per block', async () => { 293 // Bug: https://github.com/trufflesuite/truffle/issues/1389 294 const batch = web3.eth.BatchRequest(); 295 batch.add(s.reward_abi.reward.request({value: reward})); 296 batch.add(s.reward_abi.reward.request({value: reward})); 297 298 try { 299 await batch.execute(); 300 assert.fail('It must fail'); 301 } catch (e) { 302 assert.match(e.message, /Call outside of governance/); 303 } 304 }); 305 }); 306 307 describe('Single MN', () => { 308 let announced_block; 309 310 it('should refuse announce() without collateral', async () => { 311 try { 312 await s.token_abi.announce( 313 masternode1, ip1, enode1, { from: not_owner }); 314 assert.fail('It should fail'); 315 } catch (e) { 316 assert.match(e.message, /Invalid collateral/); 317 } 318 319 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(0); 320 }); 321 322 const non_routables = { 323 '127.0.0.0/8' : [ 0x7F000001, 0x7FFFFFFF ], 324 '10.0.0.0/8' : [ 0x0A000001, 0x0AFFFFFF ], 325 '172.16.0.0/12' : [ 0xAC100001, 0xAC108001 ], 326 '192.168.0.0/16' : [ 0xC0A80001, 0xC0A88001 ], 327 '0.0.0.0/8' : [ 0x00123456 ], 328 '100.64.0.0/10' : [ 0x64400001, 0x64480001 ], 329 '169.254.0.0/16' : [ 0xA9FE0001, 0xA9FEFFFF ], 330 '198.18.0.0/15' : [ 0xC6120001, 0xC613FFFF ], 331 '198.51.100.0/24' : [ 0xC6336401, 0xC63364FF ], 332 '203.0.113.0/24' : [ 0xCB007101, 0xCB0071FE ], 333 '224.0.0.0/4' : [ 0xE0000001, 0xE80FF001 ], 334 '240.0.0.0/4' : [ 0xF0000001, 0xF800FFFF ], 335 '255.255.255.255/32' : [ 0xFFFFFFFF ], 336 }; 337 338 for (let k in non_routables) { 339 it(`should refuse announce() non-routable IPs: ${k}`, async () => { 340 for (let ip of non_routables[k]) { 341 try { 342 await s.token_abi.announce( 343 masternode1, ip, enode1, { from: owner1 }); 344 assert.fail('It should fail'); 345 } catch (e) { 346 assert.match(e.message, /Wrong IP/); 347 } 348 } 349 }); 350 } 351 352 it('should announce()', async () => { 353 const res = await s.mntoken_abi.balanceInfo(owner1); 354 assert.equal(res['0'].valueOf(), collateral1); 355 356 await s.token_abi.announce( 357 masternode1, ip1, enode1, { from: owner1 }); 358 359 const ann_e = await s.orig.getPastEvents('Announced', common.evt_last_block); 360 expect(ann_e).lengthOf(1); 361 common.stringifyBN(web3, ann_e[0].args); 362 expect(ann_e[0].args).deep.include({ 363 '0': masternode1, 364 '1': owner1, 365 '2': ip1.toString(), 366 '3': enode1, 367 '4': toBN(collateral1).toString(), 368 '__length__': 5, 369 'masternode': masternode1, 370 'owner': owner1, 371 'ipv4address': ip1.toString(), 372 'enode': enode1, 373 'collateral': toBN(collateral1).toString(), 374 }); 375 376 const den_e = await s.orig.getPastEvents('Denounced', common.evt_last_block); 377 expect(den_e).lengthOf(0); 378 }); 379 380 it('should re-announce MN', async () => { 381 await s.token_abi.announce( 382 masternode1, ip1, enode1, { from: owner1 }); 383 384 const ann_e = await s.orig.getPastEvents('Announced', common.evt_last_block); 385 expect(ann_e).lengthOf(1); 386 expect(ann_e[0].args).deep.include({ 387 '0': masternode1, 388 '1': owner1, 389 '2': ip1, 390 '3': enode1, 391 '4': toBN(collateral1), 392 '__length__': 5, 393 'masternode': masternode1, 394 'owner': owner1, 395 'ipv4address': ip1, 396 'enode': enode1, 397 'collateral': toBN(collateral1), 398 }); 399 400 const den_e = await s.orig.getPastEvents('Denounced', common.evt_last_block); 401 expect(den_e).lengthOf(1); 402 expect(den_e[0].args).deep.include({ 403 '0': masternode1, 404 '1': owner1, 405 '__length__': 2, 406 'masternode': masternode1, 407 'owner': owner1, 408 }); 409 410 announced_block = await web3.eth.getBlockNumber(); 411 }); 412 413 it('should refuse announce() another owner\'s MN', async () => { 414 try { 415 await s.token_abi.announce( 416 masternode1, ip2, enode2, { from: owner2 }); 417 assert.fail('It should fail'); 418 } catch (e) { 419 assert.match(e.message, /Invalid owner/); 420 } 421 422 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(0); 423 }); 424 425 it('should refuse denounce() another owner\'s MN', async () => { 426 try { 427 await s.token_abi.denounce(masternode1, { from: owner2 }); 428 assert.fail('It should fail'); 429 } catch (e) { 430 assert.match(e.message, /Invalid owner/); 431 } 432 433 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(0); 434 }); 435 436 it('should forbid heartbeat() at wrong time', async () => { 437 const bn = await web3.eth.getBlockNumber(); 438 const b = await web3.eth.getBlock(bn); 439 440 // The first must succeed 441 await s.token_abi.heartbeat(bn, b.hash, sw_features, {from: masternode1, ...common.zerofee_callopts}); 442 443 try { 444 await s.token_abi.heartbeat(bn, b.hash, sw_features, {from: masternode1, ...common.zerofee_callopts}); 445 assert.fail('It should fail'); 446 } catch (e) { 447 assert.match(e.message, /Too early/); 448 } 449 450 await common.moveTime(web3, 59*30); 451 452 try { 453 await s.token_abi.heartbeat(bn, b.hash, sw_features, {from: masternode1, ...common.zerofee_callopts}); 454 assert.fail('It should fail'); 455 } catch (e) { 456 assert.match(e.message, /Too early/); 457 } 458 }); 459 460 it('should be isActive()', async () => { 461 expect(await s.token_abi.isActive(masternode1)).true; 462 expect(await s.token_abi.isActive(masternode2)).false; 463 }); 464 465 it('should handle onCollateralUpdate()', async () => { 466 await s.token_abi.onCollateralUpdate(owner1); 467 await s.token_abi.onCollateralUpdate(owner2); 468 expect(await s.token_abi.isActive(masternode1)).true; 469 expect(await s.token_abi.isActive(masternode2)).false; 470 }); 471 472 it('should canHeartbeat()', async () => { 473 expect(await s.token_abi.canHeartbeat(masternode1)).false; 474 expect(await s.token_abi.canHeartbeat(masternode2)).false; 475 476 await common.moveTime(web3, 60*30+1); 477 478 expect(await s.token_abi.canHeartbeat(masternode1)).true; 479 expect(await s.token_abi.canHeartbeat(masternode2)).false; 480 }); 481 482 it('should heartbeat()', async () => { 483 const s1 = await s.orig.mn_status(masternode1); 484 const bn = await web3.eth.getBlockNumber(); 485 const b = await web3.eth.getBlock(bn); 486 487 await s.token_abi.heartbeat(bn, b.hash, sw_features, {from: masternode1, ...common.zerofee_callopts}); 488 489 const s2 = await s.orig.mn_status(masternode1); 490 expect(s2.next_heartbeat.gt(s1.next_heartbeat)).true; 491 expect(s2.next_heartbeat.gt(b.timestamp)).true; 492 493 await checkHeartbeat(); 494 }); 495 496 it('should correctly count', async () => { 497 const res = await s.token_abi.count(); 498 assert.equal(res[0], 1); 499 assert.equal(res[1], 1); 500 assert.equal(res[2].toString(), collateral1.toString()); 501 }); 502 503 it('should produce info()', async () => { 504 const info = await s.token_abi.info(masternode1); 505 common.stringifyBN(web3, info); 506 expect(info).deep.include({ 507 owner: owner1, 508 ipv4address: toBN(ip1).toString(), 509 enode: enode1, 510 collateral: toBN(collateral1).toString(), 511 sw_features: sw_features.toString(), 512 }); 513 }); 514 515 it('should produce ownerInfo()', async () => { 516 const info = await s.token_abi.ownerInfo(owner1); 517 common.stringifyBN(web3, info); 518 expect(info).deep.include({ 519 masternode: masternode1, 520 ipv4address: toBN(ip1).toString(), 521 enode: enode1, 522 collateral: toBN(collateral1).toString(), 523 announced_block: announced_block.toString(), 524 sw_features: sw_features.toString(), 525 }); 526 }); 527 528 it('should process reward()', async () => { 529 const treasury_before = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 530 const owner_before = toBN(await web3.eth.getBalance(owner1)); 531 const count = 3; 532 533 for (let i = count; i > 0; --i) { 534 const r = await s.reward_abi.getReward(i); 535 expect(r).eql(reward); 536 await s.reward_abi.reward({ 537 from: owner2, 538 value: r 539 }); 540 } 541 542 const treasury_after = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 543 expect(treasury_before.toString()).equal(treasury_after.toString()); 544 545 const owner_after = toBN(await web3.eth.getBalance(owner1)); 546 expect(owner_after.sub(owner_before).toString()) 547 .eql(reward.mul(toBN(count)).toString()); 548 }); 549 550 it('should handle onCollateralUpdate()', async () => { 551 await s.token_abi.onCollateralUpdate(owner1); 552 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(0); 553 }); 554 555 it('should handle enumerate()', async () => { 556 expect(await s.token_abi.enumerate()).members([masternode1]); 557 }); 558 559 it('should forbid heartbeat() too late', async () => { 560 const bn = await web3.eth.getBlockNumber(); 561 const b = await web3.eth.getBlock(bn); 562 563 expect(await s.token_abi.canHeartbeat(masternode1)).false; 564 565 try { 566 await s.token_abi.heartbeat(bn, b.hash, sw_features, {from: masternode1, ...common.zerofee_callopts}); 567 assert.fail('It should fail'); 568 } catch (e) { 569 assert.match(e.message, /Too early/); 570 } 571 572 const mn1_status = await s.orig.mn_status(masternode1); 573 let to_move = (mn1_status.next_heartbeat.add(toBN(2*60*60+1))); 574 to_move = to_move.sub(toBN((await web3.eth.getBlock('latest')).timestamp)); 575 576 await common.moveTime(web3, to_move.toNumber()); 577 578 expect(await s.token_abi.canHeartbeat(masternode1)).false; 579 580 try { 581 await s.token_abi.heartbeat(bn, b.hash, '0', {from: masternode1, ...common.zerofee_callopts}); 582 assert.fail('It should fail'); 583 } catch (e) { 584 assert.match(e.message, /Not active/); 585 } 586 587 // Denounce does not happen on read-only 588 expect(await s.orig.getPastEvents( 589 'Denounced', common.evt_last_block)).lengthOf(0); 590 }); 591 592 it('should denounce() on collateral withdrawal', async() => { 593 await s.token_abi.announce( 594 masternode1, ip1, enode1, { from: owner1 }); 595 596 await s.mntoken_abi.withdrawCollateral(collateral1, {from: owner1}); 597 598 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 599 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(0); 600 expect(await s.token_abi.enumerate()).members([]); 601 }); 602 603 it('should re-announce() on collateral change', async() => { 604 // Initial 605 await s.mntoken_abi.depositCollateral({ 606 from: owner1, 607 value: collateral1, 608 }); 609 await s.token_abi.announce( 610 masternode1, ip1, enode1, { from: owner1 }); 611 612 // Change + 613 await s.mntoken_abi.depositCollateral({ 614 from: owner1, 615 value: collateral1, 616 }); 617 618 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 619 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(1); 620 expect(await s.token_abi.enumerate()).members([masternode1]); 621 622 // Change - 623 await s.mntoken_abi.withdrawCollateral(collateral1, {from: owner1}); 624 625 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 626 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(1); 627 expect(await s.token_abi.enumerate()).members([masternode1]); 628 }); 629 630 it('should denounce()', async()=> { 631 await s.token_abi.denounce(masternode1, { from: owner1 }); 632 const evt = await s.orig.getPastEvents('Denounced', common.evt_last_block); 633 expect(evt).lengthOf(1); 634 expect(evt[0].args).deep.include({ 635 '0': masternode1, 636 '1': owner1, 637 '__length__': 2, 638 'masternode': masternode1, 639 'owner': owner1, 640 }); 641 }); 642 }); 643 644 describe('Two MN', () => { 645 const nodes = [ 646 { 647 masternode: masternode1, 648 ip: ip1, 649 enode: enode1, 650 owner: owner1, 651 collateral: collateral1, 652 }, 653 { 654 masternode: masternode2, 655 ip: ip2, 656 enode: enode2, 657 owner: owner2, 658 collateral: collateral2, 659 }, 660 ]; 661 662 it('should announce()', async () => { 663 for (let mn of nodes) { 664 await s.token_abi.announce( 665 mn.masternode, mn.ip, mn.enode, { from: mn.owner }); 666 } 667 668 const mn1_status = await s.orig.mn_status(masternode1); 669 const mn2_status = await s.orig.mn_status(masternode2); 670 expect(mn1_status.seq_payouts.toString()).equal('3'); 671 expect(mn2_status.seq_payouts.toString()).equal('2'); 672 }); 673 674 it('should re-announce MN', async () => { 675 // back order to test current being left in place first 676 for (let mn of Array.from(nodes).reverse()) { 677 await s.token_abi.announce( 678 mn.masternode, mn.ip, mn.enode, { from: mn.owner }); 679 680 const ann_e = await s.orig.getPastEvents('Announced', common.evt_last_block); 681 expect(ann_e).lengthOf(1); 682 common.stringifyBN(web3, ann_e[0].args); 683 expect(ann_e[0].args).deep.include({ 684 '0': mn.masternode, 685 '1': mn.owner, 686 '2': toBN(mn.ip).toString(), 687 '3': mn.enode, 688 '4': toBN(mn.collateral).toString(), 689 '__length__': 5, 690 'masternode': mn.masternode, 691 'owner': mn.owner, 692 'ipv4address': toBN(mn.ip).toString(), 693 'enode': mn.enode, 694 'collateral': toBN(mn.collateral).toString(), 695 }); 696 697 const den_e = await s.orig.getPastEvents('Denounced', common.evt_last_block); 698 expect(den_e).lengthOf(1); 699 common.stringifyBN(web3, den_e[0].args); 700 expect(den_e[0].args).deep.include({ 701 '0': mn.masternode, 702 '1': mn.owner, 703 '__length__': 2, 704 'masternode': mn.masternode, 705 'owner': mn.owner, 706 }); 707 } 708 }); 709 710 it('should refuse announce() another owner\'s MN', async () => { 711 try { 712 await s.token_abi.announce( 713 masternode1, ip2, enode2, { from: owner2 }); 714 assert.fail('It should fail'); 715 } catch (e) { 716 assert.match(e.message, /Invalid owner/); 717 } 718 719 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(0); 720 }); 721 722 it('should refuse denounce() another owner\'s MN', async () => { 723 try { 724 await s.token_abi.denounce(masternode1, { from: owner2 }); 725 assert.fail('It should fail'); 726 } catch (e) { 727 assert.match(e.message, /Invalid owner/); 728 } 729 730 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(0); 731 }); 732 733 it('should be isActive()', async () => { 734 for (let mn of nodes) { 735 expect(await s.token_abi.isActive(mn.masternode)).true; 736 } 737 }); 738 739 it('should heartbeat()', async () => { 740 await common.moveTime(web3, 60*30+1); 741 742 const s1 = await s.orig.mn_status(masternode1); 743 const s1o = await s.orig.mn_status(masternode2); 744 const bn = await web3.eth.getBlockNumber(); 745 const b = await web3.eth.getBlock(bn); 746 747 await s.token_abi.heartbeat(bn, b.hash, sw_features, {from: masternode1, ...common.zerofee_callopts}); 748 749 const s2 = await s.orig.mn_status(masternode1); 750 expect(s2.next_heartbeat.gt(s1.next_heartbeat)).true; 751 expect(s2.next_heartbeat.gt(b.timestamp)).true; 752 753 const s2o = await s.orig.mn_status(masternode2); 754 expect(s2o.next_heartbeat.eq(s1o.next_heartbeat)).true; 755 756 await checkHeartbeat(); 757 }); 758 759 it('should correctly count', async () => { 760 const res = await s.token_abi.count(); 761 common.stringifyBN(web3, res); 762 expect(res).eql({ 763 '0': '2', 764 '1': '2', 765 '2': toWei('5000', 'ether'), 766 '3': toWei('5000', 'ether'), 767 '4': toWei('10000', 'ether'), 768 'active': '2', 769 'total': '2', 770 'active_collateral': toWei('5000', 'ether'), 771 'total_collateral': toWei('5000', 'ether'), 772 'max_of_all_times': toWei('10000', 'ether'), 773 }); 774 }); 775 776 it('should produce info()', async () => { 777 for (let mn of nodes) { 778 const info = await s.token_abi.info(mn.masternode); 779 common.stringifyBN(web3, info); 780 expect(info).deep.include({ 781 owner: mn.owner, 782 ipv4address: toBN(mn.ip).toString(), 783 enode: mn.enode, 784 collateral: toBN(mn.collateral).toString(), 785 sw_features: (mn.masternode === masternode1) ? sw_features.toString() : '0', 786 }); 787 } 788 }); 789 790 it('should process reward()', async () => { 791 const treasury_before = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 792 const owner1_before = toBN(await web3.eth.getBalance(owner1)); 793 const owner2_before = toBN(await web3.eth.getBalance(owner2)); 794 const count = 10; 795 let sb = false; 796 797 for (let i = count; i > 0; --i) { 798 let r = await s.reward_abi.getReward(i); 799 if (r.eq(toBN(0))) { 800 // superblock case 801 r = await s.reward_abi.getReward(i+1); 802 sb = true; 803 } 804 805 expect(r.toString()).eql(reward.toString()); 806 807 await s.reward_abi.reward({ 808 from: owner3, 809 value: r 810 }); 811 } 812 813 expect(sb).true; 814 815 const treasury_after = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 816 expect(treasury_before.toString()).equal(treasury_after.toString()); 817 818 const owner1_after = toBN(await web3.eth.getBalance(owner1)); 819 const owner2_after = toBN(await web3.eth.getBalance(owner2)); 820 expect(owner1_after.sub(owner1_before).toString()) 821 .eql(reward.mul(toBN(6)).toString()); 822 expect(owner2_after.sub(owner2_before).toString()) 823 .eql(reward.mul(toBN(4)).toString()); 824 }); 825 826 it('should handle enumerate()', async () => { 827 expect(await s.token_abi.enumerate()).members([masternode1, masternode2]); 828 }); 829 830 it('should denounce() on collateral withdrawal', async() => { 831 await s.token_abi.announce( 832 masternode1, ip1, enode1, { from: owner1 }); 833 834 await s.mntoken_abi.withdrawCollateral(collateral1, {from: owner1}); 835 836 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 837 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(0); 838 expect(await s.token_abi.enumerate()).members([masternode2]); 839 }); 840 841 it('should re-announce() on collateral change', async() => { 842 // Initial 843 await s.mntoken_abi.depositCollateral({ 844 from: owner1, 845 value: collateral1, 846 }); 847 await s.token_abi.announce( 848 masternode1, ip1, enode1, { from: owner1 }); 849 850 // Change + 851 await s.mntoken_abi.depositCollateral({ 852 from: owner1, 853 value: collateral1, 854 }); 855 856 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 857 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(1); 858 expect(await s.token_abi.enumerate()).members([masternode1, masternode2]); 859 860 // Change - 861 await s.mntoken_abi.withdrawCollateral(collateral1, {from: owner1}); 862 863 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 864 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(1); 865 expect(await s.token_abi.enumerate()).members([masternode1, masternode2]); 866 }); 867 868 it('should denounce()', async()=> { 869 for (let mn of nodes) { 870 await s.token_abi.denounce(mn.masternode, { from: mn.owner }); 871 const evt = await s.orig.getPastEvents('Denounced', common.evt_last_block); 872 expect(evt).lengthOf(1); 873 expect(evt[0].args).deep.include({ 874 '0': mn.masternode, 875 '1': mn.owner, 876 '__length__': 2, 877 'masternode': mn.masternode, 878 'owner': mn.owner, 879 }); 880 } 881 }); 882 }); 883 884 describe('Three MN', () => { 885 const nodes = [ 886 { 887 masternode: masternode1, 888 ip: ip1, 889 enode: enode1, 890 owner: owner1, 891 collateral: collateral1, 892 }, 893 { 894 masternode: masternode2, 895 ip: ip2, 896 enode: enode2, 897 owner: owner2, 898 collateral: collateral2, 899 }, 900 { 901 masternode: masternode3, 902 ip: ip3, 903 enode: enode3, 904 owner: owner3, 905 collateral: collateral3, 906 }, 907 ]; 908 909 it('should announce()', async () => { 910 for (let mn of nodes) { 911 await s.token_abi.announce( 912 mn.masternode, mn.ip, mn.enode, { from: mn.owner }); 913 } 914 915 const mn1_status = await s.orig.mn_status(masternode1); 916 const mn2_status = await s.orig.mn_status(masternode2); 917 const mn3_status = await s.orig.mn_status(masternode3); 918 expect(mn1_status.seq_payouts.toString()).equal('3'); 919 expect(mn2_status.seq_payouts.toString()).equal('2'); 920 expect(mn3_status.seq_payouts.toString()).equal('1'); 921 }); 922 923 it('should re-announce MN', async () => { 924 // back order to test current being left in place first 925 for (let mn of Array.from(nodes).reverse()) { 926 await s.token_abi.announce( 927 mn.masternode, mn.ip, mn.enode, { from: mn.owner }); 928 929 const ann_e = await s.orig.getPastEvents('Announced', common.evt_last_block); 930 expect(ann_e).lengthOf(1); 931 common.stringifyBN(web3, ann_e[0].args); 932 expect(ann_e[0].args).deep.include({ 933 '0': mn.masternode, 934 '1': mn.owner, 935 '2': toBN(mn.ip).toString(), 936 '3': mn.enode, 937 '4': toBN(mn.collateral).toString(), 938 '__length__': 5, 939 'masternode': mn.masternode, 940 'owner': mn.owner, 941 'ipv4address': toBN(mn.ip).toString(), 942 'enode': mn.enode, 943 'collateral': toBN(mn.collateral).toString(), 944 }); 945 946 const den_e = await s.orig.getPastEvents('Denounced', common.evt_last_block); 947 expect(den_e).lengthOf(1); 948 common.stringifyBN(web3, den_e[0].args); 949 expect(den_e[0].args).deep.include({ 950 '0': mn.masternode, 951 '1': mn.owner, 952 '__length__': 2, 953 'masternode': mn.masternode, 954 'owner': mn.owner, 955 }); 956 } 957 }); 958 959 it('should be isActive()', async () => { 960 for (let mn of nodes) { 961 expect(await s.token_abi.isActive(mn.masternode)).true; 962 expect(await s.token_abi.isActive(mn.owner)).false; 963 } 964 }); 965 966 it('should correctly count', async () => { 967 const res = await s.token_abi.count(); 968 common.stringifyBN(web3, res); 969 expect(res).eql({ 970 '0': '3', 971 '1': '3', 972 '2': toWei('6000', 'ether'), 973 '3': toWei('6000', 'ether'), 974 '4': toWei('10000', 'ether'), 975 'active': '3', 976 'total': '3', 977 'active_collateral': toWei('6000', 'ether'), 978 'total_collateral': toWei('6000', 'ether'), 979 'max_of_all_times': toWei('10000', 'ether'), 980 }); 981 }); 982 983 it('should produce info()', async () => { 984 for (let mn of nodes) { 985 const info = await s.token_abi.info(mn.masternode); 986 common.stringifyBN(web3, info); 987 expect(info).deep.include({ 988 owner: mn.owner, 989 ipv4address: toBN(mn.ip).toString(), 990 enode: mn.enode, 991 collateral: toBN(mn.collateral).toString(), 992 sw_features: '0', 993 }); 994 } 995 }); 996 997 it('should process reward()', async () => { 998 const treasury_before = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 999 const owner1_before = toBN(await web3.eth.getBalance(owner1)); 1000 const owner2_before = toBN(await web3.eth.getBalance(owner2)); 1001 const owner3_before = toBN(await web3.eth.getBalance(owner3)); 1002 const count = 18; 1003 let sb = false; 1004 1005 for (let i = count; i > 0; --i) { 1006 let r = await s.reward_abi.getReward(i); 1007 if (r.eq(toBN(0))) { 1008 // superblock case 1009 r = await s.reward_abi.getReward(i+1); 1010 sb = true; 1011 } 1012 1013 expect(r.toString()).eql(reward.toString()); 1014 1015 await s.reward_abi.reward({ 1016 from: not_owner, 1017 value: r 1018 }); 1019 1020 const target1 = await s.token_abi.validationTarget(masternode1); 1021 const target2 = await s.token_abi.validationTarget(masternode2); 1022 const target3 = await s.token_abi.validationTarget(masternode3); 1023 expect(target1).not.equal(masternode1); 1024 expect(target2).not.equal(masternode2); 1025 expect(target3).not.equal(masternode3); 1026 expect(target1).not.equal(target2); 1027 expect(target1).not.equal(target3); 1028 1029 if (i > 6 && i < 12 || i == 13) { 1030 let t = target1; 1031 1032 if (await isTargetChanges(s.token_abi, masternode1)) { 1033 // still a chance of fail. 1034 t = (t === masternode3) ? masternode2 : masternode3; 1035 } 1036 1037 const invalidator = (t === masternode3) ? masternode1 : masternode2; 1038 1039 if (await s.token_abi.canInvalidate(invalidator)) { 1040 await s.token_abi.invalidate(masternode3, {from: invalidator}); 1041 } 1042 } 1043 } 1044 1045 expect(sb).true; 1046 1047 // One invalidation at round 2 1048 const treasury_after = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 1049 expect(treasury_after.sub(treasury_before).toString()) 1050 .eql(reward.mul(toBN(1)).toString()) 1051 1052 const owner1_after = toBN(await web3.eth.getBalance(owner1)); 1053 const owner2_after = toBN(await web3.eth.getBalance(owner2)); 1054 const owner3_after = toBN(await web3.eth.getBalance(owner3)); 1055 expect(owner1_after.sub(owner1_before).toString()) 1056 .eql(reward.mul(toBN(3+3+3)).toString()); 1057 expect(owner2_after.sub(owner2_before).toString()) 1058 .eql(reward.mul(toBN(2+2+2)).toString()); 1059 expect(owner3_after.sub(owner3_before).toString()) 1060 .eql(reward.mul(toBN(1+0+1)).toString()); 1061 }); 1062 1063 1064 it('should calculate validation target by periods', async () => { 1065 let bn = await web3.eth.getBlockNumber(); 1066 const valTarget = () => { 1067 return s.token_abi.methods['validationTarget(address)'](masternode1, bn); 1068 } 1069 1070 let tmp = await valTarget(); 1071 let target = tmp; 1072 1073 do { 1074 --bn; 1075 target = await valTarget(); 1076 } while ( target === tmp ); 1077 1078 const obn = bn; 1079 1080 for (let i = vperiod; i > 0; --i, --bn) { 1081 tmp = await valTarget(); 1082 expect(tmp).equal(target); 1083 } 1084 1085 bn = obn + 1; 1086 1087 for (let i = vperiod; i > 0; --i, ++bn) { 1088 tmp = await valTarget(); 1089 expect(tmp).not.equal(target); 1090 } 1091 }); 1092 1093 it('should refuse invalidate() wrong target', async () => { 1094 try { 1095 let target = await s.token_abi.validationTarget(masternode1); 1096 1097 if ((target == masternode2) && !await isTargetChanges(s.token_abi, masternode1)) { 1098 target = masternode3; 1099 } else { 1100 target = masternode2; 1101 } 1102 1103 await s.token_abi.invalidate(target, {from:masternode1, ...common.zerofee_callopts}); 1104 assert.fail('It must fail'); 1105 } catch (e) { 1106 assert.match(e.message, /Invalid target/); 1107 } 1108 }); 1109 1110 it('should process reward() deactivate missing heartbeat', async () => { 1111 await common.moveTime(web3, 40*60); 1112 1113 { 1114 const b = await web3.eth.getBlock('latest'); 1115 await s.token_abi.heartbeat(b.number, b.hash, '12', {from:masternode1, ...common.zerofee_callopts}); 1116 await s.token_abi.heartbeat(b.number, b.hash, '23', {from:masternode2, ...common.zerofee_callopts}); 1117 await s.token_abi.heartbeat(b.number, b.hash, '34', {from:masternode3, ...common.zerofee_callopts}); 1118 } 1119 1120 await common.moveTime(web3, 70*60); 1121 1122 const treasury_before = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 1123 const owner1_before = toBN(await web3.eth.getBalance(owner1)); 1124 const owner2_before = toBN(await web3.eth.getBalance(owner2)); 1125 const owner3_before = toBN(await web3.eth.getBalance(owner3)); 1126 const count = 18; 1127 let sb = false; 1128 1129 for (let i = count; i > 0; --i) { 1130 if (i == 12 || i == 8 || i == 4) { 1131 const bn = await web3.eth.getBlockNumber(); 1132 const b = await web3.eth.getBlock(bn); 1133 await s.token_abi.heartbeat(bn, b.hash, '12', {from:masternode1, ...common.zerofee_callopts}); 1134 await s.token_abi.heartbeat(bn, b.hash, '34', {from:masternode3, ...common.zerofee_callopts}); 1135 await common.moveTime(web3, 91*60); 1136 } 1137 1138 let r = await s.reward_abi.getReward(i); 1139 if (r.eq(toBN(0))) { 1140 // superblock case 1141 r = await s.reward_abi.getReward(i+1); 1142 sb = true; 1143 } 1144 1145 expect(r.toString()).eql(reward.toString()); 1146 1147 await s.reward_abi.reward({ 1148 from: not_owner, 1149 value: r, 1150 }); 1151 } 1152 1153 expect(sb).true; 1154 1155 const treasury_after = toBN(await web3.eth.getBalance(s.treasury_impl.address)); 1156 const owner1_after = toBN(await web3.eth.getBalance(owner1)); 1157 const owner2_after = toBN(await web3.eth.getBalance(owner2)); 1158 const owner3_after = toBN(await web3.eth.getBalance(owner3)); 1159 1160 // The treasury must get reward of nodes without votes by design 1161 expect(treasury_after.sub(treasury_before).toString()) 1162 .eql(reward.mul(toBN(0)).toString()) 1163 expect(owner1_after.sub(owner1_before).toString()) 1164 .eql(reward.mul(toBN(3+3+3+3)).toString()); 1165 expect(owner2_after.sub(owner2_before).toString()) 1166 .eql(reward.mul(toBN(2+0+0+0)).toString()); 1167 expect(owner3_after.sub(owner3_before).toString()) 1168 .eql(reward.mul(toBN(1+1+1+1)).toString()); 1169 1170 expect(await s.token_abi.isActive(masternode1)).true; 1171 expect(await s.token_abi.isActive(masternode2)).false; 1172 expect(await s.token_abi.isActive(masternode3)).true; 1173 }); 1174 1175 it('should skip inactive node from validation', async () => { 1176 const target1 = await s.token_abi.validationTarget(masternode1); 1177 const target3 = await s.token_abi.validationTarget(masternode3); 1178 expect(target1).eql(masternode3); 1179 expect(target3).eql(masternode1); 1180 }); 1181 1182 it('should canInvalidate()', async () => { 1183 expect(await s.token_abi.canInvalidate(masternode1)).true; 1184 expect(await s.token_abi.canInvalidate(masternode2)).false; 1185 expect(await s.token_abi.canInvalidate(masternode3)).true; 1186 }); 1187 1188 it('should refuse invalidate() by inactive node', async () => { 1189 try { 1190 await s.token_abi.invalidate(masternode1, {from:masternode2, ...common.zerofee_callopts}); 1191 assert.fail('It must fail'); 1192 } catch (e) { 1193 assert.match(e.message, /Not active caller/); 1194 } 1195 }); 1196 1197 it('should refuse double invalidate()', async () => { 1198 expect(await s.token_abi.canInvalidate(masternode1)).true; 1199 expect(await s.token_abi.canInvalidate(masternode3)).true; 1200 await s.token_abi.invalidate(masternode3, {from:masternode1, ...common.zerofee_callopts}); 1201 expect(await s.token_abi.canInvalidate(masternode1)).false; 1202 expect(await s.token_abi.canInvalidate(masternode3)).true; 1203 1204 try { 1205 for (let i = 0; i < vperiod; ++i) { 1206 await s.token_abi.invalidate(masternode3, {from:masternode1, ...common.zerofee_callopts}); 1207 } 1208 assert.fail('It must fail'); 1209 } catch (e) { 1210 assert.match(e.message, /Already invalidated/); 1211 } 1212 }); 1213 1214 it('should handle enumerate()', async () => { 1215 expect(await s.token_abi.enumerate()).members([ 1216 masternode1, masternode2, masternode3]); 1217 }); 1218 1219 it('should handle enumerateActive()', async () => { 1220 expect(await s.token_abi.enumerateActive()).members([ 1221 masternode1, masternode3]); 1222 }); 1223 1224 it('should denounce() on collateral withdrawal', async() => { 1225 await s.token_abi.announce( 1226 masternode1, ip1, enode1, { from: owner1 }); 1227 1228 await s.mntoken_abi.withdrawCollateral(collateral1, {from: owner1}); 1229 1230 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 1231 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(0); 1232 expect(await s.token_abi.enumerate()).members([masternode2, masternode3]); 1233 }); 1234 1235 it('should re-announce() on collateral change', async() => { 1236 // Initial 1237 await s.mntoken_abi.depositCollateral({ 1238 from: owner1, 1239 value: collateral1, 1240 }); 1241 await s.token_abi.announce( 1242 masternode1, ip1, enode1, { from: owner1 }); 1243 1244 // Change + 1245 await s.mntoken_abi.depositCollateral({ 1246 from: owner1, 1247 value: collateral1, 1248 }); 1249 1250 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 1251 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(1); 1252 expect(await s.token_abi.enumerate()).members([masternode1, masternode2, masternode3]); 1253 1254 // Change - 1255 await s.mntoken_abi.withdrawCollateral(collateral1, {from: owner1}); 1256 1257 expect(await s.orig.getPastEvents('Denounced', common.evt_last_block)).lengthOf(1); 1258 expect(await s.orig.getPastEvents('Announced', common.evt_last_block)).lengthOf(1); 1259 expect(await s.token_abi.enumerate()).members([masternode1, masternode2, masternode3]); 1260 }); 1261 1262 it('should cleanup inactive node', async () => { 1263 await common.moveTime(web3, 25*60*60); 1264 1265 for (let i = 4; i > 0; --i) { 1266 await s.reward_abi.reward({ 1267 from: not_owner, 1268 value: reward 1269 }); 1270 } 1271 1272 expect(await s.token_abi.enumerate()).members([masternode1, masternode3]); 1273 }); 1274 1275 it('should denounce()', async()=> { 1276 for (let mn of nodes) { 1277 await s.token_abi.denounce(mn.masternode, { from: mn.owner }); 1278 const evt = await s.orig.getPastEvents('Denounced', common.evt_last_block); 1279 1280 if (mn.masternode == masternode2) { 1281 expect(evt).lengthOf(0); 1282 continue; 1283 } 1284 1285 expect(evt).lengthOf(1); 1286 expect(evt[0].args).deep.include({ 1287 '0': mn.masternode, 1288 '1': mn.owner, 1289 '__length__': 2, 1290 'masternode': mn.masternode, 1291 'owner': mn.owner, 1292 }); 1293 } 1294 }); 1295 1296 it('should correctly count() ever max', async () => { 1297 const res = await s.token_abi.count(); 1298 common.stringifyBN(web3, res); 1299 expect(res).eql({ 1300 '0': '0', 1301 '1': '0', 1302 '2': toWei('0', 'ether'), 1303 '3': toWei('0', 'ether'), 1304 '4': toWei('10000', 'ether'), 1305 'active': '0', 1306 'total': '0', 1307 'active_collateral': toWei('0', 'ether'), 1308 'total_collateral': toWei('0', 'ether'), 1309 'max_of_all_times': toWei('10000', 'ether'), 1310 }); 1311 }); 1312 1313 it('should migrate from V1', async () => { 1314 const collateral = toWei('10000', 'ether'); 1315 1316 // Spork registry 1317 const registry_proxy = await MockProxy.new(); 1318 const registry = await MockSporkRegistry.new(registry_proxy.address); 1319 await registry_proxy.setImpl(registry.address); 1320 1321 // MNReg proxy 1322 const mn_proxy = await MockProxy.new(); 1323 const imn = await IMasternodeRegistryV2.at(mn_proxy.address); 1324 1325 const impl1 = await MasternodeRegistryV1.new( 1326 mn_proxy.address, 1327 s.mntoken_proxy_addr, 1328 s.treasury_proxy_addr, 1329 common.mnregistry_config 1330 ); 1331 const impl2 = await MasternodeRegistryV2.new( 1332 mn_proxy.address, 1333 s.mntoken_proxy_addr, 1334 s.treasury_proxy_addr, 1335 common.mnregistry_config_v2, 1336 common.mnreg_deploy_opts 1337 ); 1338 await mn_proxy.setImpl(impl1.address); 1339 1340 // Announce 1341 for (let mn of nodes) { 1342 if (mn.masternode === masternode3) { 1343 continue; 1344 } 1345 1346 await s.mntoken_abi.depositCollateral({ 1347 from: mn.owner, 1348 value: collateral, 1349 }); 1350 1351 await imn.announce(mn.masternode, mn.ip, mn.enode, { from: mn.owner }); 1352 } 1353 1354 expect(await imn.enumerate()).members([masternode1, masternode2]); 1355 1356 expect(await impl2.enumerate()).members([]); 1357 1358 // Upgrade 1359 const { logs } = await mn_proxy.proposeUpgrade(impl2.address, 0); 1360 s.assert.equal(logs.length, 1); 1361 1362 const proposal = await MockProposal.at(logs[0].args['1']); 1363 1364 await proposal.setAccepted(); 1365 await mn_proxy.upgrade(proposal.address); 1366 1367 // Ensure MNs are still there 1368 expect(await imn.enumerate()).members([masternode1, masternode2]); 1369 1370 expect(await impl2.enumerate()).members([masternode1, masternode2]); 1371 }); 1372 }); 1373 1374 const SPI_MN_COUNT = process.env.SPI_MN_COUNT || 10; // set to 10000 at runtime 1375 describe(`${SPI_MN_COUNT} MNs`, () => { 1376 const nodes = []; 1377 1378 let mntoken_orig; 1379 let mntoken_proxy; 1380 let mnreg_orig; 1381 let mnreg_proxy; 1382 let mnreg_abi; 1383 let reward_abi; 1384 1385 before(async () => { 1386 mntoken_proxy = await MockProxy.new(); 1387 mnreg_proxy = await MockProxy.new(); 1388 1389 mntoken_orig = await MockMasternodeTokenV2.new( 1390 mntoken_proxy.address, mnreg_proxy.address, 1391 common.mnreg_deploy_opts); 1392 await mntoken_proxy.setImpl(mntoken_orig.address); 1393 1394 const params = common.mnregistry_config_v2.slice(); 1395 params[4] = 10; 1396 1397 mnreg_orig = await MasternodeRegistryV2.new( 1398 mnreg_proxy.address, 1399 mntoken_proxy.address, 1400 s.treasury_proxy_addr, 1401 params, 1402 common.mnreg_deploy_opts 1403 ); 1404 await mnreg_proxy.setImpl(mnreg_orig.address); 1405 mnreg_abi = await IMasternodeRegistryV2.at(mnreg_orig.address); 1406 reward_abi = await IBlockReward.at(mnreg_orig.address); 1407 }); 1408 1409 it('should generate metadata', async function() { 1410 this.timeout(7200e3); 1411 const c1k = toBN(toWei('1000', 'ether')); 1412 const for_fees = toBN(toWei('1', 'ether')); 1413 const e1 = fromAscii('12345678901234567890123456789012'); 1414 1415 for (let i = 1; i <= SPI_MN_COUNT; ++i) { 1416 const e2 = (i.toString() + '000000').repeat(10).substr(0, 32); 1417 const masternode = await web3.eth.personal.newAccount(''); 1418 const owner = await web3.eth.personal.newAccount(''); 1419 const collateral = c1k.mul(toBN(1 + i%100)); 1420 1421 await web3.eth.personal.unlockAccount(masternode, '', 0); 1422 await web3.eth.personal.unlockAccount(owner, '', 0); 1423 1424 nodes.push({ 1425 masternode, 1426 owner, 1427 ip: ip1, 1428 enode: [e1, fromAscii(e2)], 1429 collateral, 1430 }); 1431 1432 await web3.eth.sendTransaction({ 1433 to: owner, 1434 from: owner1, 1435 value: for_fees, 1436 }); 1437 await web3.eth.sendTransaction({ 1438 to: masternode, 1439 from: owner1, 1440 value: for_fees, 1441 }); 1442 await mntoken_orig.setBalance(owner, collateral); 1443 1444 if (i%100 === 0) { 1445 // eslint-disable-next-line no-console 1446 console.log(`Done ${i}`); 1447 } 1448 } 1449 }); 1450 1451 it('should announce all', async function() { 1452 this.timeout(7200e3); 1453 let i = 0; 1454 1455 for (let n of nodes) { 1456 await mnreg_abi.announce(n.masternode, n.ip, n.enode, { 1457 from: n.owner 1458 }); 1459 1460 if (++i%100 === 0) { 1461 // eslint-disable-next-line no-console 1462 console.log(`Done ${i}`); 1463 } 1464 } 1465 }); 1466 1467 it('should simulate operation', async function() { 1468 this.timeout(7200e3); 1469 let i = 0; 1470 1471 await common.moveTime(web3, 60*30); 1472 1473 for (let { masternode } of nodes) { 1474 if (!await mnreg_abi.canHeartbeat(masternode)) { 1475 const status = await mnreg_orig.mn_status(masternode); 1476 let to_move = status.next_heartbeat.add(toBN(1)); 1477 to_move = to_move.sub(toBN(await web3.eth.getBlock('latest')).timestamp); 1478 1479 await common.moveTime(web3, to_move.toNumber()); 1480 } 1481 1482 const bn = await web3.eth.getBlockNumber(); 1483 const b = await web3.eth.getBlock(bn); 1484 1485 await mnreg_abi.heartbeat(bn, b.hash, '0', { 1486 from: masternode, 1487 ...common.zerofee_callopts, 1488 }); 1489 await reward_abi.reward({value: reward}); 1490 1491 if (++i%100 === 0) { 1492 // eslint-disable-next-line no-console 1493 console.log(`Done ${i}`); 1494 } 1495 } 1496 }); 1497 }); 1498 }); 1499 1500 //--- 1501 describe('common post', () => common.govPostTests(s) ); 1502 });