// Copyright 2018 The dexon-consensus Authors // This file is part of the dexon-consensus library. // // The dexon-consensus library is free software: you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // The dexon-consensus library is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser // General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the dexon-consensus library. If not, see // . package vm import ( "bytes" "crypto/ecdsa" "math/big" "math/rand" "sort" "testing" "time" coreCommon "github.com/dexon-foundation/dexon-consensus/common" dexCore "github.com/dexon-foundation/dexon-consensus/core" coreCrypto "github.com/dexon-foundation/dexon-consensus/core/crypto" coreEcdsa "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa" coreTypes "github.com/dexon-foundation/dexon-consensus/core/types" coreUtils "github.com/dexon-foundation/dexon-consensus/core/utils" "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" "github.com/dexon-foundation/dexon/rlp" "github.com/stretchr/testify/suite" ) func init() { rand.Seed(time.Now().UnixNano()) } func randomBytes(minLength, maxLength int32) []byte { length := minLength if maxLength != minLength { length += rand.Int31() % (maxLength - minLength) } b := make([]byte, length) for i := range b { b[i] = byte(65 + rand.Int31()%60) } return b } type GovernanceStateTestSuite struct { suite.Suite s *GovernanceState } func (g *GovernanceStateTestSuite) SetupTest() { db := state.NewDatabase(ethdb.NewMemDatabase()) statedb, err := state.New(common.Hash{}, db) if err != nil { panic(err) } g.s = &GovernanceState{statedb} } func (g *GovernanceStateTestSuite) TestReadWriteEraseBytes() { for i := 0; i < 100; i++ { // Short bytes. loc := big.NewInt(rand.Int63()) data := randomBytes(3, 32) g.s.writeBytes(loc, data) read := g.s.readBytes(loc) g.Require().Equal(0, bytes.Compare(data, read)) g.s.eraseBytes(loc) read = g.s.readBytes(loc) g.Require().Len(read, 0) // long bytes. loc = big.NewInt(rand.Int63()) data = randomBytes(33, 2560) g.s.writeBytes(loc, data) read = g.s.readBytes(loc) g.Require().Equal(0, bytes.Compare(data, read)) g.s.eraseBytes(loc) read = g.s.readBytes(loc) g.Require().Len(read, 0) } } func (g *GovernanceStateTestSuite) TestReadWriteErase1DArray() { for j := 0; j < 50; j++ { idx := big.NewInt(int64(j)) data := make([][]byte, 30) for key := range data { data[key] = randomBytes(3, 32) g.s.appendTo1DByteArray(idx, data[key]) } read := g.s.read1DByteArray(idx) g.Require().Len(read, len(data)) for key := range data { g.Require().Equal(0, bytes.Compare(data[key], read[key])) } g.s.erase1DByteArray(idx) read = g.s.read1DByteArray(idx) g.Require().Len(read, 0) } } func TestGovernanceState(t *testing.T) { suite.Run(t, new(GovernanceStateTestSuite)) } type OracleContractsTestSuite struct { suite.Suite context Context config *params.DexconConfig memDB *ethdb.MemDatabase stateDB *state.StateDB s *GovernanceState } func (g *OracleContractsTestSuite) SetupTest() { memDB := ethdb.NewMemDatabase() stateDB, err := state.New(common.Hash{}, state.NewDatabase(memDB)) if err != nil { panic(err) } g.memDB = memDB g.stateDB = stateDB g.s = &GovernanceState{stateDB} config := params.TestnetChainConfig.Dexcon config.LockupPeriod = 1000 config.NextHalvingSupply = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2.5e9)) config.LastHalvedAmount = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1.5e9)) config.MiningVelocity = 0.1875 config.DKGSetSize = 7 g.config = config // Give governance contract balance so it will not be deleted because of being an empty state object. stateDB.AddBalance(GovernanceContractAddress, big.NewInt(1)) // Genesis CRS. crs := crypto.Keccak256Hash([]byte(config.GenesisCRSText)) g.s.SetCRS(crs) // Round 0 height. g.s.PushRoundHeight(big.NewInt(0)) // Owner. g.s.SetOwner(g.config.Owner) // Governance configuration. g.s.UpdateConfiguration(config) g.stateDB.Commit(true) g.context = Context{ CanTransfer: func(db StateDB, addr common.Address, amount *big.Int) bool { return db.GetBalance(addr).Cmp(amount) >= 0 }, Transfer: func(db StateDB, sender common.Address, recipient common.Address, amount *big.Int) { db.SubBalance(sender, amount) db.AddBalance(recipient, amount) }, GetRoundHeight: func(round uint64) (uint64, bool) { switch round { case 0: return 0, true case 1: return 1000, true case 2: return 2000, true } return 0, false }, StateAtNumber: func(n uint64) (*state.StateDB, error) { return g.stateDB, nil }, BlockNumber: big.NewInt(0), } } func (g *OracleContractsTestSuite) TearDownTest() { OracleContracts[GovernanceContractAddress].(*GovernanceContract).coreDKGUtils = &defaultCoreDKGUtils{} } func (g *OracleContractsTestSuite) newPrefundAccount() (*ecdsa.PrivateKey, common.Address) { privKey, err := crypto.GenerateKey() if err != nil { panic(err) } address := crypto.PubkeyToAddress(privKey.PublicKey) g.stateDB.AddBalance(address, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2e6))) return privKey, address } func (g *OracleContractsTestSuite) call( contractAddr common.Address, caller common.Address, input []byte, value *big.Int) ([]byte, error) { g.context.Time = big.NewInt(time.Now().UnixNano() / 1000000) evm := NewEVM(g.context, g.stateDB, params.TestChainConfig, Config{IsBlockProposer: true}) ret, _, err := evm.Call(AccountRef(caller), contractAddr, input, 10000000, value) return ret, err } func (g *OracleContractsTestSuite) TestTransferOwnership() { _, addr := g.newPrefundAccount() input, err := GovernanceABI.ABI.Pack("transferOwnership", addr) g.Require().NoError(err) // Call with non-owner. _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NotNil(err) // Call with owner. _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(addr, g.s.Owner()) } func (g *OracleContractsTestSuite) TestStakeUnstakeWithoutExtraDelegators() { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)) balanceBeforeStake := g.stateDB.GetBalance(addr) input, err := GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) g.Require().Equal(1, int(g.s.LenNodes().Uint64())) g.Require().Equal(1, len(g.s.QualifiedNodes())) g.Require().Equal("Test1", g.s.Node(big.NewInt(0)).Name) g.Require().Equal(amount.String(), g.s.TotalStaked().String()) // Check balance. g.Require().Equal(new(big.Int).Sub(balanceBeforeStake, amount), g.stateDB.GetBalance(addr)) g.Require().Equal(new(big.Int).Add(big.NewInt(1), amount), g.stateDB.GetBalance(GovernanceContractAddress)) // Staking again should fail. _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NotNil(err) // Unstake. input, err = GovernanceABI.ABI.Pack("unstake") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(0, len(g.s.QualifiedNodes())) g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64())) g.Require().Equal(1, int(g.s.LenNodes().Uint64())) node := g.s.Node(big.NewInt(0)) g.Require().Equal(big.NewInt(0).String(), node.Staked.String()) g.Require().Equal(big.NewInt(0).String(), g.s.TotalStaked().String()) // Wait for lockup time than withdraw. time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(0, len(g.s.QualifiedNodes())) g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64())) g.Require().Equal(0, int(g.s.LenNodes().Uint64())) // Stake 2 nodes, and unstake the first then the second. // 2nd node Stake. privKey2, addr2 := g.newPrefundAccount() pk2 := crypto.FromECDSAPub(&privKey2.PublicKey) input, err = GovernanceABI.ABI.Pack("stake", pk2, "Test2", "test2@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr2, input, amount) g.Require().NoError(err) g.Require().Equal("Test2", g.s.Node(big.NewInt(0)).Name) g.Require().Equal(0, int(g.s.NodesOffsetByAddress(addr2).Int64())) // 1st node Stake. input, err = GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) g.Require().Equal(2, len(g.s.QualifiedNodes())) g.Require().Equal(new(big.Int).Mul(amount, big.NewInt(2)).String(), g.s.TotalStaked().String()) // 2nd node Unstake. input, err = GovernanceABI.ABI.Pack("unstake") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr2, input, big.NewInt(0)) g.Require().NoError(err) node = g.s.Node(big.NewInt(0)) g.Require().Equal("Test2", node.Name) g.Require().Equal(big.NewInt(0).String(), node.Staked.String()) g.Require().Equal(1, len(g.s.QualifiedNodes())) g.Require().Equal(amount.String(), g.s.TotalStaked().String()) time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr2) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr2, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(1, len(g.s.QualifiedNodes())) g.Require().Equal(1, int(g.s.LenNodes().Uint64())) g.Require().Equal("Test1", g.s.Node(big.NewInt(0)).Name) g.Require().Equal(-1, int(g.s.NodesOffsetByAddress(addr2).Int64())) // 1st node Unstake. input, err = GovernanceABI.ABI.Pack("unstake") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(0, len(g.s.QualifiedNodes())) g.Require().Equal(big.NewInt(0).String(), g.s.TotalStaked().String()) time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(0, int(g.s.LenNodes().Uint64())) g.Require().Equal(-1, int(g.s.NodesOffsetByAddress(addr).Int64())) g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addr).Int64())) // Check balance. g.Require().Equal(balanceBeforeStake, g.stateDB.GetBalance(addr)) g.Require().Equal(balanceBeforeStake, g.stateDB.GetBalance(addr2)) g.Require().Equal(big.NewInt(1), g.stateDB.GetBalance(GovernanceContractAddress)) } func (g *OracleContractsTestSuite) TestDelegateUndelegate() { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) // Stake. input, err := GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) ownerStaked := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) _, err = g.call(GovernanceContractAddress, addr, input, ownerStaked) g.Require().NoError(err) g.Require().Equal(0, len(g.s.QualifiedNodes())) g.Require().Equal(addr, g.s.Delegator(addr, big.NewInt(0)).Owner) g.Require().Equal(ownerStaked, g.s.Node(big.NewInt(0)).Staked) // 1st delegator delegate to 1st node. _, addrDelegator := g.newPrefundAccount() balanceBeforeDelegate := g.stateDB.GetBalance(addrDelegator) amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3e5)) input, err = GovernanceABI.ABI.Pack("delegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, amount) g.Require().NoError(err) g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator)) g.Require().Equal(addrDelegator, g.s.Delegator(addr, big.NewInt(1)).Owner) g.Require().Equal(new(big.Int).Add(amount, ownerStaked), g.s.Node(big.NewInt(0)).Staked) g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String()) g.Require().Equal(1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64())) // Same person delegate the 2nd time should fail. _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(1e18)) g.Require().NotNil(err) // Not yet qualified. g.Require().Equal(0, len(g.s.QualifiedNodes())) // 2nd delegator delegate to 1st node. _, addrDelegator2 := g.newPrefundAccount() _, err = g.call(GovernanceContractAddress, addrDelegator2, input, amount) g.Require().NoError(err) g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator2)) g.Require().Equal(addrDelegator2, g.s.Delegator(addr, big.NewInt(2)).Owner) g.Require().Equal(new(big.Int).Add(ownerStaked, new(big.Int).Mul(amount, big.NewInt(2))), g.s.Node(big.NewInt(0)).Staked) g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String()) g.Require().Equal(2, int(g.s.DelegatorsOffset(addr, addrDelegator2).Int64())) // Qualified. g.Require().Equal(1, len(g.s.QualifiedNodes())) // Undelegate addrDelegator. balanceBeforeUnDelegate := g.stateDB.GetBalance(addrDelegator) input, err = GovernanceABI.ABI.Pack("undelegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().Equal(new(big.Int).Add(amount, ownerStaked), g.s.Node(big.NewInt(0)).Staked) g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String()) g.Require().NoError(err) // Undelegate the second time should fail. _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().Error(err) // Withdraw within lockup time should fail. input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().NotNil(err) g.Require().Equal(3, int(g.s.LenDelegators(addr).Uint64())) g.Require().Equal(balanceBeforeUnDelegate, g.stateDB.GetBalance(addrDelegator)) g.Require().NotEqual(-1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64())) // Wait for lockup time than withdraw. time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(2, int(g.s.LenDelegators(addr).Uint64())) g.Require().Equal(new(big.Int).Add(balanceBeforeUnDelegate, amount), g.stateDB.GetBalance(addrDelegator)) g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64())) // Withdraw when their is no delegation should fail. time.Sleep(time.Second) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().Error(err) // Undelegate addrDelegator2. balanceBeforeUnDelegate = g.stateDB.GetBalance(addrDelegator2) input, err = GovernanceABI.ABI.Pack("undelegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator2, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(ownerStaked, g.s.Node(big.NewInt(0)).Staked) g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String()) // Wait for lockup time than withdraw. time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator2, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64())) g.Require().Equal(new(big.Int).Add(balanceBeforeUnDelegate, amount), g.stateDB.GetBalance(addrDelegator2)) g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addrDelegator2).Int64())) // Unqualified g.Require().Equal(0, len(g.s.QualifiedNodes())) // Owner undelegate itself. g.Require().Equal(1, int(g.s.LenNodes().Uint64())) g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64())) input, err = GovernanceABI.ABI.Pack("undelegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(big.NewInt(0).String(), g.s.Node(big.NewInt(0)).Staked.String()) g.Require().Equal(big.NewInt(0).String(), g.s.TotalStaked().String()) time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().Equal(0, int(g.s.LenNodes().Uint64())) g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64())) } func (g *OracleContractsTestSuite) TestFine() { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) // Stake. input, err := GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) ownerStaked := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) _, err = g.call(GovernanceContractAddress, addr, input, ownerStaked) g.Require().NoError(err) g.Require().Equal(0, len(g.s.QualifiedNodes())) g.Require().Equal(addr, g.s.Delegator(addr, big.NewInt(0)).Owner) g.Require().Equal(ownerStaked, g.s.Node(big.NewInt(0)).Staked) // 1st delegator delegate to 1st node. _, addrDelegator := g.newPrefundAccount() balanceBeforeDelegate := g.stateDB.GetBalance(addrDelegator) amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) input, err = GovernanceABI.ABI.Pack("delegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, amount) g.Require().NoError(err) g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator)) g.Require().Equal(addrDelegator, g.s.Delegator(addr, big.NewInt(1)).Owner) g.Require().Equal(new(big.Int).Add(amount, ownerStaked), g.s.Node(big.NewInt(0)).Staked) g.Require().Equal(1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64())) // Qualified. g.Require().Equal(1, len(g.s.QualifiedNodes())) // Paying to node without fine should fail. input, err = GovernanceABI.ABI.Pack("payFine", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, amount) g.Require().NotNil(err) // Fined. offset := g.s.NodesOffsetByAddress(addr) g.Require().True(offset.Cmp(big.NewInt(0)) >= 0) node := g.s.Node(offset) node.Fined = new(big.Int).Set(amount) g.s.UpdateNode(offset, node) node = g.s.Node(offset) g.Require().Equal(0, node.Fined.Cmp(amount)) // Not qualified after fined. g.Require().Equal(0, len(g.s.QualifiedNodes())) // Cannot undelegate before fines are paied. input, err = GovernanceABI.ABI.Pack("undelegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().NotNil(err) // Only delegators can pay fine. _, addrDelegator2 := g.newPrefundAccount() input, err = GovernanceABI.ABI.Pack("payFine", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator2, input, big.NewInt(5e5)) g.Require().NotNil(err) // Paying more than fine should fail. payAmount := new(big.Int).Add(amount, amount) input, err = GovernanceABI.ABI.Pack("payFine", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, payAmount) g.Require().NotNil(err) // Pay the fine. input, err = GovernanceABI.ABI.Pack("payFine", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, amount) g.Require().NoError(err) // Qualified. g.Require().Equal(1, len(g.s.QualifiedNodes())) // Can undelegate after all fines are paied. input, err = GovernanceABI.ABI.Pack("undelegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().NoError(err) } func (g *OracleContractsTestSuite) TestUnstakeWithExtraDelegators() { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) input, err := GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) // 1st delegator delegate to 1st node. _, addrDelegator := g.newPrefundAccount() balanceBeforeDelegate := g.stateDB.GetBalance(addrDelegator) amount = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3e5)) input, err = GovernanceABI.ABI.Pack("delegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, amount) g.Require().NoError(err) g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator)) g.Require().Equal(addrDelegator, g.s.Delegator(addr, big.NewInt(1)).Owner) g.Require().Equal(0, len(g.s.QualifiedNodes())) // 2st delegator delegate to 1st node. _, addrDelegator2 := g.newPrefundAccount() balanceBeforeDelegate = g.stateDB.GetBalance(addrDelegator2) input, err = GovernanceABI.ABI.Pack("delegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator2, input, amount) g.Require().NoError(err) g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator2)) g.Require().Equal(addrDelegator2, g.s.Delegator(addr, big.NewInt(2)).Owner) // Node is now qualified. g.Require().Equal(1, len(g.s.QualifiedNodes())) // Unstake. input, err = GovernanceABI.ABI.Pack("unstake") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) time.Sleep(time.Second * 2) input, err = GovernanceABI.ABI.Pack("withdraw", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, big.NewInt(0)) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator2, input, big.NewInt(0)) g.Require().NoError(err) g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64())) g.Require().Equal(0, int(g.s.LenNodes().Uint64())) // Check balance. g.Require().Equal(balanceBeforeDelegate, g.stateDB.GetBalance(addr)) g.Require().Equal(balanceBeforeDelegate, g.stateDB.GetBalance(addrDelegator)) g.Require().Equal(balanceBeforeDelegate, g.stateDB.GetBalance(addrDelegator2)) g.Require().Equal(big.NewInt(1), g.stateDB.GetBalance(GovernanceContractAddress)) } func (g *OracleContractsTestSuite) TestUpdateConfiguration() { _, addr := g.newPrefundAccount() input, err := GovernanceABI.ABI.Pack("updateConfiguration", new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)), big.NewInt(1000), big.NewInt(8000000), big.NewInt(250), big.NewInt(2500), big.NewInt(4), big.NewInt(4), big.NewInt(600), big.NewInt(900), []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}, big.NewInt(2e9)) g.Require().NoError(err) // Call with non-owner. _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NotNil(err) // Call with owner. _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) g.Require().NoError(err) } func (g *OracleContractsTestSuite) TestConfigurationReading() { _, addr := g.newPrefundAccount() // CRS. input, err := GovernanceABI.ABI.Pack("crs") g.Require().NoError(err) res, err := g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var crs0 [32]byte err = GovernanceABI.ABI.Unpack(&crs0, "crs", res) g.Require().NoError(err) g.Require().Equal(crypto.Keccak256Hash([]byte(g.config.GenesisCRSText)), common.BytesToHash(crs0[:])) // Owner. input, err = GovernanceABI.ABI.Pack("owner") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var owner common.Address err = GovernanceABI.ABI.Unpack(&owner, "owner", res) g.Require().NoError(err) g.Require().Equal(g.config.Owner, owner) // MinStake. input, err = GovernanceABI.ABI.Pack("minStake") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var value *big.Int err = GovernanceABI.ABI.Unpack(&value, "minStake", res) g.Require().NoError(err) g.Require().Equal(g.config.MinStake.String(), value.String()) // BlockReward. input, err = GovernanceABI.ABI.Pack("miningVelocity") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "miningVelocity", res) g.Require().NoError(err) g.Require().Equal(g.config.MiningVelocity, float32(value.Uint64())/decimalMultiplier) // BlockGasLimit. input, err = GovernanceABI.ABI.Pack("blockGasLimit") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "blockGasLimit", res) g.Require().NoError(err) g.Require().Equal(g.config.BlockGasLimit, value.Uint64()) // LambdaBA. input, err = GovernanceABI.ABI.Pack("lambdaBA") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "lambdaBA", res) g.Require().NoError(err) g.Require().Equal(g.config.LambdaBA, value.Uint64()) // LambdaDKG. input, err = GovernanceABI.ABI.Pack("lambdaDKG") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "lambdaDKG", res) g.Require().NoError(err) g.Require().Equal(g.config.LambdaDKG, value.Uint64()) // NotarySetSize. input, err = GovernanceABI.ABI.Pack("notarySetSize") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "notarySetSize", res) g.Require().NoError(err) g.Require().Equal(g.config.NotarySetSize, uint32(value.Uint64())) // DKGSetSize. input, err = GovernanceABI.ABI.Pack("dkgSetSize") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "dkgSetSize", res) g.Require().NoError(err) g.Require().Equal(g.config.DKGSetSize, uint32(value.Uint64())) // RoundLength. input, err = GovernanceABI.ABI.Pack("roundLength") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "roundLength", res) g.Require().NoError(err) g.Require().Equal(g.config.RoundLength, value.Uint64()) // MinBlockInterval. input, err = GovernanceABI.ABI.Pack("minBlockInterval") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "minBlockInterval", res) g.Require().NoError(err) g.Require().Equal(g.config.MinBlockInterval, value.Uint64()) // MinGasPrice. input, err = GovernanceABI.ABI.Pack("minGasPrice") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "minGasPrice", res) g.Require().NoError(err) g.Require().Equal(g.config.MinGasPrice, value) } func (g *OracleContractsTestSuite) TestReportForkVote() { key, addr := g.newPrefundAccount() pkBytes := crypto.FromECDSAPub(&key.PublicKey) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) input, err := GovernanceABI.ABI.Pack("stake", pkBytes, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) pubKey := coreEcdsa.NewPublicKeyFromECDSA(&key.PublicKey) privKey := coreEcdsa.NewPrivateKeyFromECDSA(key) vote1 := coreTypes.NewVote(coreTypes.VoteCom, coreCommon.NewRandomHash(), uint64(0)) vote1.ProposerID = coreTypes.NewNodeID(pubKey) vote2 := vote1.Clone() for vote2.BlockHash == vote1.BlockHash { vote2.BlockHash = coreCommon.NewRandomHash() } vote1.Signature, err = privKey.Sign(coreUtils.HashVote(vote1)) g.Require().NoError(err) vote2.Signature, err = privKey.Sign(coreUtils.HashVote(vote2)) g.Require().NoError(err) vote1Bytes, err := rlp.EncodeToBytes(vote1) g.Require().NoError(err) vote2Bytes, err := rlp.EncodeToBytes(vote2) g.Require().NoError(err) // Report wrong type (fork block) input, err = GovernanceABI.ABI.Pack("report", big.NewInt(2), vote1Bytes, vote2Bytes) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().Error(err) input, err = GovernanceABI.ABI.Pack("report", big.NewInt(1), vote1Bytes, vote2Bytes) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) node := g.s.Node(big.NewInt(0)) g.Require().Equal(node.Fined, g.s.FineValue(big.NewInt(1))) // Duplicate report should fail. input, err = GovernanceABI.ABI.Pack("report", big.NewInt(1), vote1Bytes, vote2Bytes) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().Error(err) // Check if finedRecords is set. payloads := [][]byte{vote1Bytes, vote2Bytes} sort.Sort(sortBytes(payloads)) hash := Bytes32(crypto.Keccak256Hash(payloads...)) input, err = GovernanceABI.ABI.Pack("finedRecords", hash) g.Require().NoError(err) res, err := g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var value bool err = GovernanceABI.ABI.Unpack(&value, "finedRecords", res) g.Require().NoError(err) g.Require().True(value) } func (g *OracleContractsTestSuite) TestReportForkBlock() { key, addr := g.newPrefundAccount() pkBytes := crypto.FromECDSAPub(&key.PublicKey) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) input, err := GovernanceABI.ABI.Pack("stake", pkBytes, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) privKey := coreEcdsa.NewPrivateKeyFromECDSA(key) block1 := &coreTypes.Block{ ProposerID: coreTypes.NewNodeID(privKey.PublicKey()), ParentHash: coreCommon.NewRandomHash(), Timestamp: time.Now(), } block2 := block1.Clone() for block2.ParentHash == block1.ParentHash { block2.ParentHash = coreCommon.NewRandomHash() } hashBlock := func(block *coreTypes.Block) coreCommon.Hash { block.PayloadHash = coreCrypto.Keccak256Hash(block.Payload) var err error block.Hash, err = coreUtils.HashBlock(block) g.Require().NoError(err) return block.Hash } block1.Signature, err = privKey.Sign(hashBlock(block1)) g.Require().NoError(err) block2.Signature, err = privKey.Sign(hashBlock(block2)) g.Require().NoError(err) block1Bytes, err := rlp.EncodeToBytes(block1) g.Require().NoError(err) block2Bytes, err := rlp.EncodeToBytes(block2) g.Require().NoError(err) // Report wrong type (fork vote) input, err = GovernanceABI.ABI.Pack("report", big.NewInt(1), block1Bytes, block2Bytes) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().Error(err) input, err = GovernanceABI.ABI.Pack("report", big.NewInt(2), block1Bytes, block2Bytes) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) node := g.s.Node(big.NewInt(0)) g.Require().Equal(node.Fined, g.s.FineValue(big.NewInt(2))) // Duplicate report should fail. input, err = GovernanceABI.ABI.Pack("report", big.NewInt(2), block1Bytes, block2Bytes) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().Error(err) // Check if finedRecords is set. payloads := [][]byte{block1Bytes, block2Bytes} sort.Sort(sortBytes(payloads)) hash := Bytes32(crypto.Keccak256Hash(payloads...)) input, err = GovernanceABI.ABI.Pack("finedRecords", hash) g.Require().NoError(err) res, err := g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var value bool err = GovernanceABI.ABI.Unpack(&value, "finedRecords", res) g.Require().NoError(err) g.Require().True(value) } func (g *OracleContractsTestSuite) TestMiscVariableReading() { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) input, err := GovernanceABI.ABI.Pack("totalSupply") g.Require().NoError(err) res, err := g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) input, err = GovernanceABI.ABI.Pack("totalStaked") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) input, err = GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) // 1st delegator delegate to 1st node. _, addrDelegator := g.newPrefundAccount() amount = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3e5)) input, err = GovernanceABI.ABI.Pack("delegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator, input, amount) g.Require().NoError(err) // 2st delegator delegate to 1st node. _, addrDelegator2 := g.newPrefundAccount() input, err = GovernanceABI.ABI.Pack("delegate", addr) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrDelegator2, input, amount) g.Require().NoError(err) input, err = GovernanceABI.ABI.Pack("nodes", big.NewInt(0)) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) input, err = GovernanceABI.ABI.Pack("nodesLength") g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var value *big.Int err = GovernanceABI.ABI.Unpack(&value, "nodesLength", res) g.Require().NoError(err) g.Require().Equal(1, int(value.Uint64())) input, err = GovernanceABI.ABI.Pack("nodesOffsetByAddress", addr) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "nodesOffsetByAddress", res) g.Require().NoError(err) g.Require().Equal(0, int(value.Uint64())) id, err := publicKeyToNodeID(pk) g.Require().NoError(err) input, err = GovernanceABI.ABI.Pack("nodesOffsetByID", id) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "nodesOffsetByID", res) g.Require().NoError(err) g.Require().Equal(0, int(value.Uint64())) input, err = GovernanceABI.ABI.Pack("delegators", addr, big.NewInt(0)) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) input, err = GovernanceABI.ABI.Pack("delegatorsLength", addr) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "delegatorsLength", res) g.Require().NoError(err) g.Require().Equal(3, int(value.Uint64())) input, err = GovernanceABI.ABI.Pack("delegatorsOffset", addr, addrDelegator2) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = GovernanceABI.ABI.Unpack(&value, "delegatorsOffset", res) g.Require().NoError(err) g.Require().Equal(2, int(value.Uint64())) input, err = GovernanceABI.ABI.Pack("fineValues", big.NewInt(0)) g.Require().NoError(err) res, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) } func (g *OracleContractsTestSuite) TestHalvingCondition() { // TotalSupply 2.5B reached g.s.MiningHalved() g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3.25e9)).String(), g.s.NextHalvingSupply().String()) g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(0.75e9)).String(), g.s.LastHalvedAmount().String()) // TotalSupply 3.25B reached g.s.MiningHalved() g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3.625e9)).String(), g.s.NextHalvingSupply().String()) g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(0.375e9)).String(), g.s.LastHalvedAmount().String()) } func (g *OracleContractsTestSuite) TestNodeInfoOracleContract() { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5)) input, err := GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) // Invalid round. input, err = NodeInfoOracleABI.ABI.Pack("delegators", big.NewInt(100), addr, big.NewInt(0)) g.Require().NoError(err) res, err := g.call(NodeInfoOracleAddress, addr, input, big.NewInt(0)) g.Require().Error(err) round := big.NewInt(0) input, err = NodeInfoOracleABI.ABI.Pack("delegators", round, addr, big.NewInt(0)) g.Require().NoError(err) res, err = g.call(NodeInfoOracleAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) var value *big.Int input, err = NodeInfoOracleABI.ABI.Pack("delegatorsLength", round, addr) g.Require().NoError(err) res, err = g.call(NodeInfoOracleAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = NodeInfoOracleABI.ABI.Unpack(&value, "delegatorsLength", res) g.Require().NoError(err) g.Require().Equal(1, int(value.Uint64())) input, err = NodeInfoOracleABI.ABI.Pack("delegatorsOffset", round, addr, addr) g.Require().NoError(err) res, err = g.call(NodeInfoOracleAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) err = NodeInfoOracleABI.ABI.Unpack(&value, "delegatorsOffset", res) g.Require().NoError(err) g.Require().Equal(0, int(value.Uint64())) } type testCoreMock struct { newDKGGPKError error tsigReturn bool } func (m *testCoreMock) SetState(GovernanceState) {} func (m *testCoreMock) NewGroupPublicKey(*big.Int, int) (tsigVerifierIntf, error) { if m.newDKGGPKError != nil { return nil, m.newDKGGPKError } return &testTSigVerifierMock{m.tsigReturn}, nil } type testTSigVerifierMock struct { ret bool } func (v *testTSigVerifierMock) VerifySignature(coreCommon.Hash, coreCrypto.Signature) bool { return v.ret } func (g *OracleContractsTestSuite) TestResetDKG() { for i := uint32(0); i < g.config.DKGSetSize; i++ { privKey, addr := g.newPrefundAccount() pk := crypto.FromECDSAPub(&privKey.PublicKey) // Stake. amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)) input, err := GovernanceABI.ABI.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org") g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, amount) g.Require().NoError(err) } g.Require().Len(g.s.QualifiedNodes(), int(g.config.DKGSetSize)) addrs := make(map[int][]common.Address) dkgSets := make(map[int]map[coreTypes.NodeID]struct{}) addDKG := func(round int, final, proposeCRS bool) { if proposeCRS && uint64(round) > dexCore.DKGDelayRound { // ProposeCRS and clear DKG state. input, err := GovernanceABI.ABI.Pack( "proposeCRS", big.NewInt(int64(round)), randomBytes(32, 32)) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addrs[round-1][0], input, big.NewInt(0)) g.Require().NoError(err) // Clear DKG states for next round. dkgSet := dkgSets[round-1] g.s.ClearDKGMasterPublicKeys() g.s.ClearDKGComplaints() g.s.ClearDKGMPKReady(dkgSet) g.s.ResetDKGMPKReadysCount() g.s.ClearDKGFinalized(dkgSet) g.s.ResetDKGFinalizedsCount() g.s.SetDKGRound(big.NewInt(int64(round))) } addrs[round] = []common.Address{} target := coreTypes.NewDKGSetTarget(coreCommon.Hash(g.s.CRS())) ns := coreTypes.NewNodeSet() for _, x := range g.s.QualifiedNodes() { mpk, err := coreEcdsa.NewPublicKeyFromByteSlice(x.PublicKey) if err != nil { panic(err) } ns.Add(coreTypes.NewNodeID(mpk)) } dkgSet := ns.GetSubSet(int(g.s.DKGSetSize().Uint64()), target) g.Require().Len(dkgSet, int(g.config.DKGSetSize)) dkgSets[round] = dkgSet for id := range dkgSet { offset := g.s.NodesOffsetByID(Bytes32(id.Hash)) if offset.Cmp(big.NewInt(0)) < 0 { panic("DKG node does not exist") } node := g.s.Node(offset) // Prepare MPK. g.s.PushDKGMasterPublicKey(randomBytes(32, 64)) // Prepare Complaint. g.s.PushDKGComplaint(randomBytes(32, 64)) addr := node.Owner addrs[round] = append(addrs[round], addr) // Prepare MPK Ready. g.s.PutDKGMPKReady(addr, true) g.s.IncDKGMPKReadysCount() if final { // Prepare Finalized. g.s.PutDKGFinalized(addr, true) g.s.IncDKGFinalizedsCount() } } dkgSetSize := len(dkgSet) g.Require().Len(g.s.DKGMasterPublicKeys(), dkgSetSize) g.Require().Len(g.s.DKGComplaints(), dkgSetSize) g.Require().Equal(int64(dkgSetSize), g.s.DKGMPKReadysCount().Int64()) for _, addr := range addrs[round] { g.Require().True(g.s.DKGMPKReady(addr)) } if final { g.Require().Equal(int64(dkgSetSize), g.s.DKGFinalizedsCount().Int64()) for _, addr := range addrs[round] { g.Require().True(g.s.DKGFinalized(addr)) } } } mock := &testCoreMock{ tsigReturn: true, } OracleContracts[GovernanceContractAddress].(*GovernanceContract).coreDKGUtils = mock // Fill data for previous rounds. roundHeight := int64(g.config.RoundLength) round := int(dexCore.DKGDelayRound) + 3 for i := 0; i <= round; i++ { g.context.Round = big.NewInt(int64(i)) // Prepare Round Height if i != 0 { g.s.PushRoundHeight(big.NewInt(int64(i) * roundHeight)) } addDKG(i+1, true, true) } round++ g.s.PushRoundHeight(big.NewInt(int64(round) * roundHeight)) g.context.Round = big.NewInt(int64(round)) addDKG(round+1, false, true) repeat := 3 for r := 0; r < repeat; r++ { // Add one finalized for test. roundPlusOne := big.NewInt(int64(round + 1)) g.s.PutDKGFinalized(addrs[round+1][0], true) g.s.IncDKGFinalizedsCount() g.context.BlockNumber = big.NewInt( roundHeight*int64(round) + roundHeight*int64(r) + roundHeight*80/100) _, addr := g.newPrefundAccount() newCRS := randomBytes(common.HashLength, common.HashLength) input, err := GovernanceABI.ABI.Pack("resetDKG", newCRS) g.Require().NoError(err) _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) g.Require().NoError(err) // Test if CRS is reset. newCRSHash := crypto.Keccak256Hash(newCRS) g.Require().Equal(newCRSHash, g.s.CRS()) // Test if MPK is purged. g.Require().Len(g.s.DKGMasterPublicKeys(), 0) // Test if MPKReady is purged. g.Require().Equal(int64(0), g.s.DKGMPKReadysCount().Int64()) for _, addr := range addrs[round+1] { g.Require().False(g.s.DKGMPKReady(addr)) } // Test if Complaint is purged. g.Require().Len(g.s.DKGComplaints(), 0) // Test if Finalized is purged. g.Require().Equal(int64(0), g.s.DKGFinalizedsCount().Int64()) for _, addr := range addrs[round+1] { g.Require().False(g.s.DKGFinalized(addr)) } g.Require().Equal(int64(r+1), g.s.DKGResetCount(roundPlusOne).Int64()) addDKG(round+1, false, false) } } func TestGovernanceContract(t *testing.T) { suite.Run(t, new(OracleContractsTestSuite)) }