From 0594f51ee194bc975a75d293a789d98f47f3f4d9 Mon Sep 17 00:00:00 2001 From: Jhih-Ming Huang Date: Fri, 16 Aug 2019 08:28:50 +0000 Subject: core: add p2p whitelist for consortium --- core/vm/oracle_contract_abi.go | 946 ++++++++++++++++++++++----------------- core/vm/oracle_contracts.go | 182 +++++++- core/vm/oracle_contracts_test.go | 191 ++++++++ dex/handler.go | 33 ++ dex/handler_test.go | 77 +++- dex/helper_test.go | 11 +- p2p/peer_error.go | 1 + params/config.go | 70 ++- params/gen_dexcon_config.go | 12 + 9 files changed, 1078 insertions(+), 445 deletions(-) diff --git a/core/vm/oracle_contract_abi.go b/core/vm/oracle_contract_abi.go index 535161bd4..23ec7cd9d 100644 --- a/core/vm/oracle_contract_abi.go +++ b/core/vm/oracle_contract_abi.go @@ -55,6 +55,60 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "MinStake", + "type": "uint256" + }, + { + "name": "LockupPeriod", + "type": "uint256" + }, + { + "name": "MinGasPrice", + "type": "uint256" + }, + { + "name": "BlockGasLimit", + "type": "uint256" + }, + { + "name": "LambdaBA", + "type": "uint256" + }, + { + "name": "LambdaDKG", + "type": "uint256" + }, + { + "name": "NotaryParamAlpha", + "type": "uint256" + }, + { + "name": "NotaryParamBeta", + "type": "uint256" + }, + { + "name": "RoundLength", + "type": "uint256" + }, + { + "name": "MinBlockInterval", + "type": "uint256" + }, + { + "name": "FineValues", + "type": "uint256[]" + } + ], + "name": "updateConfiguration", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -69,6 +123,39 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "PublicKey", + "type": "bytes" + } + ], + "name": "addDKGMasterPublicKey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "addressWhitelist", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -138,6 +225,20 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "MPKReady", + "type": "bytes" + } + ], + "name": "addDKGMPKReady", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -152,6 +253,20 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "Finalize", + "type": "bytes" + } + ], + "name": "addDKGFinalize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -167,37 +282,45 @@ const GovernanceABIJSON = ` "type": "function" }, { - "constant": true, - "inputs": [], - "name": "minStake", - "outputs": [ + "constant": false, + "inputs": [ { - "name": "", + "name": "Amount", "type": "uint256" } ], + "name": "unstake", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "crsRound", - "outputs": [ + "constant": false, + "inputs": [ { - "name": "", + "name": "Type", "type": "uint256" + }, + { + "name": "Arg1", + "type": "bytes" + }, + { + "name": "Arg2", + "type": "bytes" } ], + "name": "report", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], - "name": "notaryParamAlpha", + "name": "minStake", "outputs": [ { "name": "", @@ -209,32 +332,73 @@ const GovernanceABIJSON = ` "type": "function" }, { - "constant": true, + "constant": false, "inputs": [], - "name": "dkgSuccessesCount", - "outputs": [ + "name": "stake", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ { - "name": "", - "type": "uint256" + "name": "NodeAddress", + "type": "address" + } + ], + "name": "payFine", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "NewPublicKey", + "type": "bytes" } ], + "name": "replaceNodePublicKey", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ { - "name": "", + "name": "NewOwner", "type": "address" } ], - "name": "dkgFinalizeds", + "name": "transferNodeOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "crsRound", "outputs": [ { "name": "", - "type": "bool" + "type": "uint256" } ], "payable": false, @@ -244,7 +408,7 @@ const GovernanceABIJSON = ` { "constant": true, "inputs": [], - "name": "blockGasLimit", + "name": "notaryParamAlpha", "outputs": [ { "name": "", @@ -258,7 +422,7 @@ const GovernanceABIJSON = ` { "constant": true, "inputs": [], - "name": "dkgRound", + "name": "dkgSuccessesCount", "outputs": [ { "name": "", @@ -269,20 +433,48 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "Success", + "type": "bytes" + } + ], + "name": "addDKGSuccess", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "totalStaked", + "name": "withdrawable", "outputs": [ { "name": "", - "type": "uint256" + "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "NewSignedCRS", + "type": "bytes" + } + ], + "name": "resetDKG", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -291,11 +483,11 @@ const GovernanceABIJSON = ` "type": "address" } ], - "name": "nodesOffsetByAddress", + "name": "dkgFinalizeds", "outputs": [ { "name": "", - "type": "int256" + "type": "bool" } ], "payable": false, @@ -305,11 +497,11 @@ const GovernanceABIJSON = ` { "constant": true, "inputs": [], - "name": "crs", + "name": "blockGasLimit", "outputs": [ { "name": "", - "type": "bytes32" + "type": "uint256" } ], "payable": false, @@ -319,7 +511,7 @@ const GovernanceABIJSON = ` { "constant": true, "inputs": [], - "name": "roundLength", + "name": "whitelistLength", "outputs": [ { "name": "", @@ -333,7 +525,119 @@ const GovernanceABIJSON = ` { "constant": true, "inputs": [], - "name": "nextHalvingSupply", + "name": "dkgRound", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "OldOwner", + "type": "address" + }, + { + "name": "NewOwner", + "type": "address" + } + ], + "name": "transferNodeOwnershipByFoundation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalStaked", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "nodesOffsetByAddress", + "outputs": [ + { + "name": "", + "type": "int256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "crs", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "addr", + "type": "address" + } + ], + "name": "removeFromWhitelist", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "roundLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nextHalvingSupply", "outputs": [ { "name": "", @@ -377,6 +681,25 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "whitelistOffsetByAddress", + "outputs": [ + { + "name": "", + "type": "int256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -462,6 +785,20 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "Complaint", + "type": "bytes" + } + ], + "name": "addDKGComplaint", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -528,6 +865,50 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "Round", + "type": "uint256" + }, + { + "name": "SignedCRS", + "type": "bytes" + } + ], + "name": "proposeCRS", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Name", + "type": "string" + }, + { + "name": "Email", + "type": "string" + }, + { + "name": "Location", + "type": "string" + }, + { + "name": "Url", + "type": "string" + } + ], + "name": "updateNodeInfo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -547,6 +928,36 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "PublicKey", + "type": "bytes" + }, + { + "name": "Name", + "type": "string" + }, + { + "name": "Email", + "type": "string" + }, + { + "name": "Location", + "type": "string" + }, + { + "name": "Url", + "type": "string" + } + ], + "name": "register", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -594,6 +1005,25 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "addr", + "type": "address" + } + ], + "name": "addToWhitelist", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -666,30 +1096,72 @@ const GovernanceABIJSON = ` "type": "function" }, { - "anonymous": false, - "inputs": [], - "name": "ConfigurationChanged", - "type": "event" - }, - { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": true, - "name": "Round", - "type": "uint256" - }, - { - "indexed": false, - "name": "CRS", - "type": "bytes32" + "name": "NewOwner", + "type": "address" } ], - "name": "CRSProposed", - "type": "event" - }, - { - "anonymous": false, + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nodesLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isConsortium", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [], + "name": "ConfigurationChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "Round", + "type": "uint256" + }, + { + "indexed": false, + "name": "CRS", + "type": "bytes32" + } + ], + "name": "CRSProposed", + "type": "event" + }, + { + "anonymous": false, "inputs": [ { "indexed": true, @@ -874,374 +1346,6 @@ const GovernanceABIJSON = ` ], "name": "DKGReset", "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "NewOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "MinStake", - "type": "uint256" - }, - { - "name": "LockupPeriod", - "type": "uint256" - }, - { - "name": "MinGasPrice", - "type": "uint256" - }, - { - "name": "BlockGasLimit", - "type": "uint256" - }, - { - "name": "LambdaBA", - "type": "uint256" - }, - { - "name": "LambdaDKG", - "type": "uint256" - }, - { - "name": "NotaryParamAlpha", - "type": "uint256" - }, - { - "name": "NotaryParamBeta", - "type": "uint256" - }, - { - "name": "RoundLength", - "type": "uint256" - }, - { - "name": "MinBlockInterval", - "type": "uint256" - }, - { - "name": "FineValues", - "type": "uint256[]" - } - ], - "name": "updateConfiguration", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Complaint", - "type": "bytes" - } - ], - "name": "addDKGComplaint", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "PublicKey", - "type": "bytes" - } - ], - "name": "addDKGMasterPublicKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "MPKReady", - "type": "bytes" - } - ], - "name": "addDKGMPKReady", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Finalize", - "type": "bytes" - } - ], - "name": "addDKGFinalize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Success", - "type": "bytes" - } - ], - "name": "addDKGSuccess", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "NodeAddress", - "type": "address" - } - ], - "name": "payFine", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "nodesLength", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Round", - "type": "uint256" - }, - { - "name": "SignedCRS", - "type": "bytes" - } - ], - "name": "proposeCRS", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Type", - "type": "uint256" - }, - { - "name": "Arg1", - "type": "bytes" - }, - { - "name": "Arg2", - "type": "bytes" - } - ], - "name": "report", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "NewSignedCRS", - "type": "bytes" - } - ], - "name": "resetDKG", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "PublicKey", - "type": "bytes" - }, - { - "name": "Name", - "type": "string" - }, - { - "name": "Email", - "type": "string" - }, - { - "name": "Location", - "type": "string" - }, - { - "name": "Url", - "type": "string" - } - ], - "name": "register", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "NewPublicKey", - "type": "bytes" - } - ], - "name": "replaceNodePublicKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "stake", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "NewOwner", - "type": "address" - } - ], - "name": "transferNodeOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "OldOwner", - "type": "address" - }, - { - "name": "NewOwner", - "type": "address" - } - ], - "name": "transferNodeOwnershipByFoundation", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Amount", - "type": "uint256" - } - ], - "name": "unstake", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "Name", - "type": "string" - }, - { - "name": "Email", - "type": "string" - }, - { - "name": "Location", - "type": "string" - }, - { - "name": "Url", - "type": "string" - } - ], - "name": "updateNodeInfo", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "withdrawable", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" } ] ` diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go index ddcd6d3f6..130d5bf24 100644 --- a/core/vm/oracle_contracts.go +++ b/core/vm/oracle_contracts.go @@ -99,6 +99,9 @@ const ( minBlockIntervalLoc fineValuesLoc finedRecordsLoc + isConsortiumLoc + addressWhitelistLoc + whitelistOffsetByAddressLoc ) func publicKeyToNodeKeyAddress(pkBytes []byte) (common.Address, error) { @@ -124,7 +127,7 @@ func IdToAddress(id coreTypes.NodeID) common.Address { return common.BytesToAddress(id.Hash[12:]) } -// State manipulation helper fro the governance contract. +// State manipulation helper for the governance contract. type GovernanceState struct { StateDB StateDB } @@ -984,6 +987,80 @@ func (s *GovernanceState) SetFineRecords(recordHash Bytes32, status bool) { s.setStateBigInt(loc, big.NewInt(value)) } +// bool public isConsortium; +func (s *GovernanceState) IsConsortium() bool { + return s.getStateBigInt(big.NewInt(isConsortiumLoc)).Cmp(big.NewInt(0)) > 0 +} +func (s *GovernanceState) EnableConsortium() { + s.setStateBigInt(big.NewInt(isConsortiumLoc), big.NewInt(1)) +} + +// address[] public addressWhitelist; +func (s *GovernanceState) LenWhitelist() *big.Int { + return s.getStateBigInt(big.NewInt(addressWhitelistLoc)) +} +func (s *GovernanceState) AddressWhitelist(index *big.Int) common.Address { + arrayBaseLoc := s.getSlotLoc(big.NewInt(addressWhitelistLoc)) + return common.BigToAddress(s.getStateBigInt(new(big.Int).Add(arrayBaseLoc, index))) +} +func (s *GovernanceState) AddressWhitelists() []common.Address { + len := s.LenWhitelist() + result := make([]common.Address, len.Uint64()) + for i := 0; i < int(len.Uint64()); i++ { + result[i] = s.AddressWhitelist(big.NewInt(int64(i))) + } + return result +} +func (s *GovernanceState) putAddressWhitelist(addr common.Address, offset *big.Int) { + arrayBaseLoc := s.getSlotLoc(big.NewInt(addressWhitelistLoc)) + loc := new(big.Int).Add(arrayBaseLoc, offset) + s.setState(common.BigToHash(loc), addr.Hash()) + s.putWhitelistOffsetByAddress(addr, offset) +} +func (s *GovernanceState) AddToWhitelist(addr common.Address) *big.Int { + offset := s.WhitelistOffsetByAddress(addr) + if offset.Cmp(bigZero) >= 0 { + return offset + } + len := s.getStateBigInt(big.NewInt(addressWhitelistLoc)) + s.putAddressWhitelist(addr, len) + len = new(big.Int).Add(len, big.NewInt(1)) + s.setStateBigInt(big.NewInt(addressWhitelistLoc), len) + return len +} +func (s *GovernanceState) DeleteAddressWhitelist(addr common.Address) *big.Int { + offset := s.WhitelistOffsetByAddress(addr) + if offset.Cmp(bigZero) < 0 { + return offset + } + s.DeleteWhitelistOffsetByAddress(addr) + len := s.getStateBigInt(big.NewInt(addressWhitelistLoc)) + newLen := new(big.Int).Sub(len, big.NewInt(1)) + if len.Cmp(big.NewInt(1)) > 0 && offset.Cmp(newLen) != 0 { + lastAddr := s.AddressWhitelist(newLen) + s.putAddressWhitelist(lastAddr, offset) + } + s.setStateBigInt( + big.NewInt(addressWhitelistLoc), + newLen, + ) + return len +} + +// mapping(address => int256) whitelistOffsetByAddress +func (s *GovernanceState) WhitelistOffsetByAddress(addr common.Address) *big.Int { + loc := s.getMapLoc(big.NewInt(whitelistOffsetByAddressLoc), addr.Bytes()) + return new(big.Int).Sub(s.getStateBigInt(loc), big.NewInt(1)) +} +func (s *GovernanceState) putWhitelistOffsetByAddress(addr common.Address, offset *big.Int) { + loc := s.getMapLoc(big.NewInt(whitelistOffsetByAddressLoc), addr.Bytes()) + s.setStateBigInt(loc, new(big.Int).Add(offset, big.NewInt(1))) +} +func (s *GovernanceState) DeleteWhitelistOffsetByAddress(addr common.Address) { + loc := s.getMapLoc(big.NewInt(whitelistOffsetByAddressLoc), addr.Bytes()) + s.setStateBigInt(loc, big.NewInt(0)) +} + // Initialize initializes governance contract state. func (s *GovernanceState) Initialize(config *params.DexconConfig, totalSupply *big.Int) { if config.NextHalvingSupply.Cmp(totalSupply) <= 0 { @@ -1009,6 +1086,22 @@ func (s *GovernanceState) Initialize(config *params.DexconConfig, totalSupply *b // Set DKGRound. s.SetDKGRound(big.NewInt(int64(dexCore.DKGDelayRound))) + + // Set Whitelist + s.setWhitelist(config.IsConsortium) +} + +func (s *GovernanceState) setWhitelist(isConsortium bool) { + if isConsortium { + s.EnableConsortium() + for _, node := range s.Nodes() { + address, err := publicKeyToNodeKeyAddress(node.PublicKey) + if err != nil { + panic(err) + } + s.AddToWhitelist(address) + } + } } // Register is a helper function for creating genesis state. @@ -1079,6 +1172,8 @@ func (s *GovernanceState) Configuration() *params.DexconConfig { RoundLength: s.getStateBigInt(big.NewInt(roundLengthLoc)).Uint64(), MinBlockInterval: s.getStateBigInt(big.NewInt(minBlockIntervalLoc)).Uint64(), FineValues: s.FineValues(), + AddressWhitelist: s.AddressWhitelists(), + IsConsortium: s.getStateBigInt(big.NewInt(isConsortiumLoc)).Uint64() != 0, } } @@ -1098,7 +1193,11 @@ func (s *GovernanceState) UpdateConfiguration(cfg *params.DexconConfig) { s.setStateBigInt(big.NewInt(roundLengthLoc), big.NewInt(int64(cfg.RoundLength))) s.setStateBigInt(big.NewInt(minBlockIntervalLoc), big.NewInt(int64(cfg.MinBlockInterval))) s.SetFineValues(cfg.FineValues) - + if cfg.IsConsortium { + for _, addr := range cfg.AddressWhitelist { + s.AddToWhitelist(addr) + } + } // Calculate set size. s.CalNotarySetSize() } @@ -2274,6 +2373,20 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return g.addDKGSuccess(Success) + case "addToWhitelist": + var address common.Address + if err := method.Inputs.Unpack(&address, arguments); err != nil { + return nil, errExecutionReverted + } + offset, err := g.addToWhitelist(address) + if err != nil { + return nil, errExecutionReverted + } + res, err := method.Outputs.Pack(offset) + if err != nil { + return nil, errExecutionReverted + } + return res, nil case "nodesLength": res, err := method.Outputs.Pack(g.state.LenNodes()) if err != nil { @@ -2295,6 +2408,20 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return g.proposeCRS(args.Round, args.SignedCRS) + case "removeFromWhitelist": + var address common.Address + if err := method.Inputs.Unpack(&address, arguments); err != nil { + return nil, errExecutionReverted + } + offset, err := g.removeFromWhitelist(address) + if err != nil { + return nil, errExecutionReverted + } + res, err := method.Outputs.Pack(offset) + if err != nil { + return nil, errExecutionReverted + } + return res, nil case "report": args := struct { Type *big.Int @@ -2371,6 +2498,12 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return g.updateNodeInfo(args.Name, args.Email, args.Location, args.Url) + case "whitelistLength": + res, err := method.Outputs.Pack(g.state.LenWhitelist()) + if err != nil { + return nil, errExecutionReverted + } + return res, nil case "withdraw": return g.withdraw() case "withdrawable": @@ -2379,11 +2512,21 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return res, nil - // -------------------------------- // Solidity auto generated methods. // -------------------------------- + case "addressWhitelist": + offset := new(big.Int) + if err := method.Inputs.Unpack(&offset, arguments); err != nil { + return nil, errExecutionReverted + } + address := g.state.AddressWhitelist(offset) + res, err := method.Outputs.Pack(address) + if err != nil { + return nil, errExecutionReverted + } + return res, nil case "blockGasLimit": res, err := method.Outputs.Pack(g.state.BlockGasLimit()) if err != nil { @@ -2538,6 +2681,12 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return res, nil + case "isConsortium": + res, err := method.Outputs.Pack(g.state.IsConsortium()) + if err != nil { + return nil, errExecutionReverted + } + return res, nil case "lambdaBA": res, err := method.Outputs.Pack(g.state.LambdaBA()) if err != nil { @@ -2694,7 +2843,18 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return res, nil + case "whitelistOffsetByAddress": + address := common.Address{} + if err := method.Inputs.Unpack(&address, arguments); err != nil { + return nil, errExecutionReverted + } + res, err := method.Outputs.Pack(g.state.WhitelistOffsetByAddress(address)) + if err != nil { + return nil, errExecutionReverted + } + return res, nil } + return nil, errExecutionReverted } @@ -2801,6 +2961,22 @@ func (g *GovernanceContract) replaceNodePublicKey(newPublicKey []byte) ([]byte, return nil, nil } +func (g *GovernanceContract) addToWhitelist(addr common.Address) (*big.Int, error) { + // Only owner can update whitelist. + if g.contract.Caller() != g.state.Owner() { + return nil, errExecutionReverted + } + return g.state.AddToWhitelist(addr), nil +} + +func (g *GovernanceContract) removeFromWhitelist(addr common.Address) (*big.Int, error) { + // Only owner can update whitelist. + if g.contract.Caller() != g.state.Owner() { + return nil, errExecutionReverted + } + return g.state.DeleteAddressWhitelist(addr), nil +} + func PackProposeCRS(round uint64, signedCRS []byte) ([]byte, error) { method := GovernanceABI.Name2Method["proposeCRS"] res, err := method.Inputs.Pack(big.NewInt(int64(round)), signedCRS) diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go index 192628b22..bf2f7c71a 100644 --- a/core/vm/oracle_contracts_test.go +++ b/core/vm/oracle_contracts_test.go @@ -1022,6 +1022,137 @@ func (g *GovernanceContractTestSuite) TestMiscVariableReading() { g.Require().NoError(err) } +func (g *GovernanceContractTestSuite) TestIsConsortium() { + var isConsortium bool + + _, addr1 := newPrefundAccount(g.stateDB) + + input, err := GovernanceABI.ABI.Pack("isConsortium") + g.Require().NoError(err) + res, err := g.call(GovernanceContractAddress, addr1, input, big.NewInt(0)) + g.Require().NoError(err) + err = GovernanceABI.ABI.Unpack(&isConsortium, "isConsortium", res) + g.Require().NoError(err) + g.Require().Equal(false, isConsortium) + + g.s.EnableConsortium() + res, err = g.call(GovernanceContractAddress, addr1, input, big.NewInt(0)) + g.Require().NoError(err) + err = GovernanceABI.ABI.Unpack(&isConsortium, "isConsortium", res) + g.Require().NoError(err) + g.Require().Equal(true, isConsortium) +} + +func (g *GovernanceContractTestSuite) TestUpdateWhitelist() { + checkLength := func(expectLen *big.Int) { + var length *big.Int + + lenInput, err := GovernanceABI.ABI.Pack("whitelistLength") + g.Require().NoError(err) + res, err := g.call(GovernanceContractAddress, g.config.Owner, lenInput, big.NewInt(0)) + err = GovernanceABI.ABI.Unpack(&length, "whitelistLength", res) + g.Require().NoError(err) + g.Require().Equal(expectLen.Int64(), length.Int64()) + } + check := func(addr common.Address, offset *big.Int) { + var resOffset *big.Int + var resAddr common.Address + + value := big.NewInt(0) + // check offset + input, err := GovernanceABI.ABI.Pack("whitelistOffsetByAddress", addr) + g.Require().NoError(err) + res, err := g.call(GovernanceContractAddress, addr, input, value) + g.Require().NoError(err) + err = GovernanceABI.ABI.Unpack(&resOffset, "whitelistOffsetByAddress", res) + g.Require().NoError(err) + g.Require().Equal(offset.Int64(), resOffset.Int64()) + + // check address + if offset.Cmp(big.NewInt(0)) >= 0 { + input, err = GovernanceABI.ABI.Pack("addressWhitelist", offset) + res, err = g.call(GovernanceContractAddress, addr, input, value) + g.Require().NoError(err) + err = GovernanceABI.ABI.Unpack(&resAddr, "addressWhitelist", res) + g.Require().NoError(err) + g.Require().Equal(addr, resAddr) + } + } + _, addr1 := newPrefundAccount(g.stateDB) + _, addr2 := newPrefundAccount(g.stateDB) + _, addr3 := newPrefundAccount(g.stateDB) + + input, err := GovernanceABI.ABI.Pack("addToWhitelist", addr1) + g.Require().NoError(err) + + // Call with non-owner. + _, err = g.call(GovernanceContractAddress, addr1, 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) + checkLength(big.NewInt(1)) + // duplicated call should not affect + _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) + g.Require().NoError(err) + checkLength(big.NewInt(1)) + // append addr2 + input, err = GovernanceABI.ABI.Pack("addToWhitelist", addr2) + g.Require().NoError(err) + _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) + g.Require().NoError(err) + + checkLength(big.NewInt(2)) + check(addr1, big.NewInt(0)) + check(addr2, big.NewInt(1)) + + // delete addr2 + input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr2) + g.Require().NoError(err) + // Call with non-owner. + _, err = g.call(GovernanceContractAddress, addr1, 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) + check(addr2, big.NewInt(-1)) + checkLength(big.NewInt(1)) + + // append addr2 back + input, err = GovernanceABI.ABI.Pack("addToWhitelist", addr2) + g.Require().NoError(err) + _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) + g.Require().NoError(err) + checkLength(big.NewInt(2)) + check(addr1, big.NewInt(0)) + check(addr2, big.NewInt(1)) + + // delete addr1 + input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr1) + g.Require().NoError(err) + _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) + g.Require().NoError(err) + check(addr1, big.NewInt(-1)) + check(addr2, big.NewInt(0)) + checkLength(big.NewInt(1)) + + // delete addr2 + input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr2) + g.Require().NoError(err) + _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) + g.Require().NoError(err) + check(addr1, big.NewInt(-1)) + check(addr2, big.NewInt(-1)) + checkLength(big.NewInt(0)) + + // duplicated delete addr2 + input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr2) + g.Require().NoError(err) + // delete not in whitelist address + input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr3) + g.Require().NoError(err) +} + func (g *GovernanceContractTestSuite) TestHalvingCondition() { // TotalSupply 2.5B reached g.s.MiningHalved() @@ -1244,6 +1375,66 @@ func (g *GovernanceContractTestSuite) TestResetDKG() { } } +func (g *GovernanceContractTestSuite) TestConsortium() { + g.Require().False(g.s.IsConsortium()) + g.s.EnableConsortium() + g.Require().True(g.s.IsConsortium()) +} + +func (g *GovernanceContractTestSuite) TestAddWhitelist() { + _, addr1 := newPrefundAccount(g.stateDB) + _, addr2 := newPrefundAccount(g.stateDB) + _, addr3 := newPrefundAccount(g.stateDB) + // no address in list + expectAddress := g.s.AddressWhitelist(big.NewInt(0)) + g.Require().Equal(common.Address{}, expectAddress) + expectAddrList := g.s.AddressWhitelists() + g.Require().Equal([]common.Address{}, expectAddrList) + + // insert addr + g.s.AddToWhitelist(addr1) + g.s.AddToWhitelist(addr1) // duplicated insertion should be ignored + expectAddress = g.s.AddressWhitelist(big.NewInt(0)) + g.Require().Equal(addr1, expectAddress) + expectAddrList = g.s.AddressWhitelists() + g.Require().Equal([]common.Address{addr1}, expectAddrList) + + g.s.AddToWhitelist(addr2) + expectAddress = g.s.AddressWhitelist(big.NewInt(1)) + g.Require().Equal(addr2, expectAddress) + expectAddrList = g.s.AddressWhitelists() + g.Require().Equal([]common.Address{addr1, addr2}, expectAddrList) + + offset := g.s.WhitelistOffsetByAddress(addr1) + g.Require().Equal(true, offset.Cmp(big.NewInt(0)) == 0) + offset = g.s.WhitelistOffsetByAddress(addr2) + g.Require().Equal(true, offset.Cmp(big.NewInt(1)) == 0) + offset = g.s.WhitelistOffsetByAddress(addr3) + g.Require().Equal(true, offset.Cmp(big.NewInt(-1)) == 0) + + // remove addr + g.s.DeleteAddressWhitelist(addr1) + g.s.DeleteAddressWhitelist(addr1) // duplicated remove should be ignored + + offset = g.s.WhitelistOffsetByAddress(addr1) + g.Require().Equal(true, offset.Cmp(big.NewInt(-1)) == 0) + offset = g.s.WhitelistOffsetByAddress(addr2) + g.Require().Equal(true, offset.Cmp(big.NewInt(0)) == 0) + + expectAddress = g.s.AddressWhitelist(big.NewInt(0)) + g.Require().Equal(addr2, expectAddress) + expectAddrList = g.s.AddressWhitelists() + g.Require().Equal([]common.Address{addr2}, expectAddrList) + + g.s.DeleteAddressWhitelist(addr2) + + offset = g.s.WhitelistOffsetByAddress(addr2) + g.Require().Equal(true, offset.Cmp(big.NewInt(-1)) == 0) + + expectAddrList = g.s.AddressWhitelists() + g.Require().Equal([]common.Address{}, expectAddrList) +} + func TestGovernanceContract(t *testing.T) { suite.Run(t, new(GovernanceContractTestSuite)) } diff --git a/dex/handler.go b/dex/handler.go index ca26bc6e8..4c1ed9a36 100644 --- a/dex/handler.go +++ b/dex/handler.go @@ -41,6 +41,7 @@ import ( "errors" "fmt" "math" + "math/big" "sync" "sync/atomic" "time" @@ -55,6 +56,7 @@ import ( "github.com/tangerine-network/go-tangerine/consensus" "github.com/tangerine-network/go-tangerine/core" "github.com/tangerine-network/go-tangerine/core/types" + "github.com/tangerine-network/go-tangerine/core/vm" "github.com/tangerine-network/go-tangerine/crypto" dexDB "github.com/tangerine-network/go-tangerine/dex/db" "github.com/tangerine-network/go-tangerine/dex/downloader" @@ -89,6 +91,7 @@ const ( maxAgreementResultBroadcast = 3 maxFinalizedBlockBroadcast = 3 + checkPeerDuration = 10 * time.Minute ) // errIncompatibleConfig is returned if the requested protocols and configs are @@ -349,6 +352,7 @@ func (pm *ProtocolManager) ReportBadPeerChan() chan<- interface{} { } func (pm *ProtocolManager) badPeerWatchLoop() { + go pm.checkPeerInWhitelist(pm.reportBadPeerChan) for { select { case id := <-pm.reportBadPeerChan: @@ -360,13 +364,42 @@ func (pm *ProtocolManager) badPeerWatchLoop() { } } +func (pm *ProtocolManager) checkPeerInWhitelist(reportBadPeerChan chan<- interface{}) { + for { + for id, p := range pm.peers.peers { + if !pm.inWhitelist(p) { + reportBadPeerChan <- id + } + } + time.Sleep(checkPeerDuration) + } +} + func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { return newPeer(pv, p, newMeteredMsgWriter(rw)) } +func (pm *ProtocolManager) inWhitelist(p *peer) bool { + state, err := pm.blockchain.State() + if err != nil { + p.Log().Debug("get state fail in checking whitelist", "err", err) + return false + } + govState := vm.GovernanceState{StateDB: state} + if !govState.IsConsortium() { + return true + } + address := crypto.PubkeyToAddress(*p.Node().Pubkey()) + return govState.WhitelistOffsetByAddress(address).Cmp(big.NewInt(0)) >= 0 +} + // handle is the callback invoked to manage the life cycle of an eth peer. When // this function terminates, the peer is disconnected. func (pm *ProtocolManager) handle(p *peer) error { + if !pm.inWhitelist(p) { + p.Log().Debug("Peer disconnect: permission denied", "name", p.Name()) + return p2p.DiscPermissionDenied + } // Ignore maxPeers if this is a trusted peer if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { return p2p.DiscTooManyPeers diff --git a/dex/handler_test.go b/dex/handler_test.go index 80f36ae9e..f276e1e4a 100644 --- a/dex/handler_test.go +++ b/dex/handler_test.go @@ -17,9 +17,12 @@ package dex import ( + "fmt" + "io/ioutil" "math" "math/big" "math/rand" + "net" "testing" "github.com/tangerine-network/go-tangerine/common" @@ -30,6 +33,7 @@ import ( "github.com/tangerine-network/go-tangerine/dex/downloader" "github.com/tangerine-network/go-tangerine/ethdb" "github.com/tangerine-network/go-tangerine/p2p" + "github.com/tangerine-network/go-tangerine/p2p/enode" "github.com/tangerine-network/go-tangerine/params" ) @@ -52,7 +56,7 @@ func TestProtocolCompatibility(t *testing.T) { for i, tt := range tests { ProtocolVersions = []uint{tt.version} - pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil) + pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil, params.TestChainConfig) if pm != nil { defer pm.Stop() } @@ -444,3 +448,74 @@ func testGetReceipt(t *testing.T, protocol int) { t.Errorf("receipts mismatch: %v", err) } } + +func TestHandlerWithConsoritum62(t *testing.T) { testHandlerWithConsoritum(t, 62) } +func TestHandlerWithConsoritum63(t *testing.T) { testHandlerWithConsoritum(t, 63) } + +func testHandlerWithConsoritum(t *testing.T, version int) { + key, err := crypto.GenerateKey() + if err != nil { + t.Errorf("gen key fail %v", err) + } + + // set config and create protocol manager + config := params.NewTestChainConig() + config.ChainID = big.NewInt(int64(DefaultConfig.NetworkId)) + config.Dexcon = params.NewTestDexonConfig() + config.Dexcon.IsConsortium = true + pm, _, err := newTestProtocolManager(downloader.FullSync, 0, nil, nil, config) + defer pm.Stop() + if err != nil { + t.Fatalf("Failed to create protocol manager: %v", err) + } + + // create peer + pipenet1, pipenet2 := p2p.MsgPipe() + defer func() { + pipenet1.Close() + pipenet2.Close() + }() + node := enode.NewV4(&key.PublicKey, net.IP{}, 0, 0) + peer := pm.newPeer(version, p2p.NewPeerWithEnode(node, "handlerTest", nil), pipenet1) + + // try to call handle, and should get permission denied error + if err := pm.handle(peer); err != p2p.DiscPermissionDenied { + t.Errorf("Expect get DiscPermissionDenied, but get %v", err) + } + + // add address to whitelist, and create new pm + address := crypto.PubkeyToAddress(key.PublicKey) + config.Dexcon.AddressWhitelist = []common.Address{address} + pm2, _, err := newTestProtocolManager(downloader.FullSync, 0, nil, nil, config) + defer pm2.Stop() + + if err != nil { + t.Fatalf("Failed to create protocol manager: %v", err) + } + handleErr := make(chan error) + go func() { + handleErr <- pm2.handle(peer) + }() + // do the handshake + msg, err := pipenet2.ReadMsg() + ioutil.ReadAll(msg.Payload) + p2p.Send(pipenet2, 0, + statusData{ + ProtocolVersion: uint32(version), + NetworkId: config.ChainID.Uint64(), + Number: 0, + CurrentBlock: common.Hash{}, + GenesisBlock: pm2.blockchain.Genesis().Hash(), + }, + ) + // send status code to terminate the handleMsg loop + p2p.Send(pipenet2, StatusMsg, struct{}{}) + err = <-handleErr + expectError := fmt.Errorf("%v - %v", + errorToString[ErrExtraStatusMsg], + "uncontrolled status message", + ) + if err.Error() != expectError.Error() { + t.Errorf("err not match, expect: %s, but got: %s", expectError, err) + } +} diff --git a/dex/helper_test.go b/dex/helper_test.go index 6e2cd3d77..5e171fef0 100644 --- a/dex/helper_test.go +++ b/dex/helper_test.go @@ -110,13 +110,18 @@ func (a *testApp) SubscribeNewFinalizedBlockEvent( // newTestProtocolManager creates a new protocol manager for testing purposes, // with the given number of blocks already known, and potential notification // channels for different events. -func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase, error) { +func newTestProtocolManager(mode downloader.SyncMode, + blocks int, + generator func(int, *core.BlockGen), + newtx chan<- []*types.Transaction, + chainConfig *params.ChainConfig, +) (*ProtocolManager, *ethdb.MemDatabase, error) { var ( evmux = new(event.TypeMux) engine = ethash.NewFaker() db = ethdb.NewMemDatabase() gspec = &core.Genesis{ - Config: params.TestChainConfig, + Config: chainConfig, Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000), Staked: big.NewInt(0)}}, } genesis = gspec.MustCommit(db) @@ -150,7 +155,7 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func // channels for different events. In case of an error, the constructor force- // fails the test. func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase) { - pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx) + pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx, params.TestChainConfig) if err != nil { t.Fatalf("Failed to create protocol manager: %v", err) } diff --git a/p2p/peer_error.go b/p2p/peer_error.go index ab61bfef0..f410b76a8 100644 --- a/p2p/peer_error.go +++ b/p2p/peer_error.go @@ -69,6 +69,7 @@ const ( DiscUnexpectedIdentity DiscSelf DiscReadTimeout + DiscPermissionDenied DiscSubprotocolError = 0x10 ) diff --git a/params/config.go b/params/config.go index c884b8cdc..b00fc6ee9 100644 --- a/params/config.go +++ b/params/config.go @@ -267,22 +267,24 @@ func (c *CliqueConfig) String() string { // DexconConfig is the consensus engine configs for DEXON consensus. type DexconConfig struct { - GenesisCRSText string `json:"genesisCRSText"` - Owner common.Address `json:"owner"` - MinStake *big.Int `json:"minStake"` - LockupPeriod uint64 `json:"lockupPeriod"` - MiningVelocity float32 `json:"miningVelocity"` - NextHalvingSupply *big.Int `json:"nextHalvingSupply"` - LastHalvedAmount *big.Int `json:"lastHalvedAmount"` - MinGasPrice *big.Int `json:"minGasPrice"` - BlockGasLimit uint64 `json:"blockGasLimit"` - LambdaBA uint64 `json:"lambdaBA"` - LambdaDKG uint64 `json:"lambdaDKG"` - NotaryParamAlpha float32 `json:"notaryParamAlpha"` - NotaryParamBeta float32 `json:"notaryParamBeta"` - RoundLength uint64 `json:"roundLength"` - MinBlockInterval uint64 `json:"minBlockInterval"` - FineValues []*big.Int `json:"fineValues"` + GenesisCRSText string `json:"genesisCRSText"` + Owner common.Address `json:"owner"` + MinStake *big.Int `json:"minStake"` + LockupPeriod uint64 `json:"lockupPeriod"` + MiningVelocity float32 `json:"miningVelocity"` + NextHalvingSupply *big.Int `json:"nextHalvingSupply"` + LastHalvedAmount *big.Int `json:"lastHalvedAmount"` + MinGasPrice *big.Int `json:"minGasPrice"` + BlockGasLimit uint64 `json:"blockGasLimit"` + LambdaBA uint64 `json:"lambdaBA"` + LambdaDKG uint64 `json:"lambdaDKG"` + NotaryParamAlpha float32 `json:"notaryParamAlpha"` + NotaryParamBeta float32 `json:"notaryParamBeta"` + RoundLength uint64 `json:"roundLength"` + MinBlockInterval uint64 `json:"minBlockInterval"` + FineValues []*big.Int `json:"fineValues"` + IsConsortium bool `json:"isConsortium"` + AddressWhitelist []common.Address `json:"addressWhitelist"` } type dexconConfigSpecMarshaling struct { @@ -295,7 +297,7 @@ type dexconConfigSpecMarshaling struct { // String implements the stringer interface, returning the consensus engine details. func (d *DexconConfig) String() string { - return fmt.Sprintf("{GenesisCRSText: %v Owner: %v MinStake: %v LockupPeriod: %v MiningVelocity: %v NextHalvingSupply: %v LastHalvedAmount: %v MinGasPrice: %v BlockGasLimit: %v LambdaBA: %v LambdaDKG: %v NotaryParamAlpha: %v NotaryParamBeta: %v RoundLength: %v MinBlockInterval: %v FineValues: %v}", + return fmt.Sprintf("{GenesisCRSText: %v Owner: %v MinStake: %v LockupPeriod: %v MiningVelocity: %v NextHalvingSupply: %v LastHalvedAmount: %v MinGasPrice: %v BlockGasLimit: %v LambdaBA: %v LambdaDKG: %v NotaryParamAlpha: %v NotaryParamBeta: %v RoundLength: %v MinBlockInterval: %v FineValues: %v IsConsortium: %v AddressWhitelist: %v}", d.GenesisCRSText, d.Owner, d.MinStake, @@ -312,6 +314,8 @@ func (d *DexconConfig) String() string { d.RoundLength, d.MinBlockInterval, d.FineValues, + d.IsConsortium, + d.AddressWhitelist, ) } @@ -552,3 +556,35 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { IsPetersburg: c.IsPetersburg(num), } } + +// NewTestChainConfig is the ChainConfig constructor for test +func NewTestChainConig() *ChainConfig { + return &ChainConfig{big.NewInt(1), 0, big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, nil} +} + +func NewTestDexonConfig() *DexconConfig { + return &DexconConfig{ + GenesisCRSText: "Tangerine Testnet", + Owner: common.HexToAddress("0x0D54AF942d6bF13870F5CA65D470954f21D3cBE5"), + MinStake: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)), + LockupPeriod: 3600, + MiningVelocity: 0.18, + NextHalvingSupply: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(125e6)), + LastHalvedAmount: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(75e6)), + MinGasPrice: new(big.Int).Mul(big.NewInt(1e9), big.NewInt(1)), + BlockGasLimit: 210000000, + LambdaBA: 250, + LambdaDKG: 20000, + NotaryParamAlpha: 70.5, + NotaryParamBeta: 264, + RoundLength: 3600, + MinBlockInterval: 1000, + FineValues: []*big.Int{ + new(big.Int).Mul(big.NewInt(1e18), big.NewInt(100)), + new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1)), + new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)), + new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)), + new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)), + }, + } +} diff --git a/params/gen_dexcon_config.go b/params/gen_dexcon_config.go index 28e2775ff..2a8d84546 100644 --- a/params/gen_dexcon_config.go +++ b/params/gen_dexcon_config.go @@ -31,6 +31,8 @@ func (d DexconConfig) MarshalJSON() ([]byte, error) { RoundLength uint64 `json:"roundLength"` MinBlockInterval uint64 `json:"minBlockInterval"` FineValues []*math.HexOrDecimal256 `json:"fineValues"` + IsConsortium bool `json:"isConsortium"` + AddressWhitelist []common.Address `json:"addressWhitelist"` } var enc DexconConfig enc.GenesisCRSText = d.GenesisCRSText @@ -54,6 +56,8 @@ func (d DexconConfig) MarshalJSON() ([]byte, error) { enc.FineValues[k] = (*math.HexOrDecimal256)(v) } } + enc.IsConsortium = d.IsConsortium + enc.AddressWhitelist = d.AddressWhitelist return json.Marshal(&enc) } @@ -76,6 +80,8 @@ func (d *DexconConfig) UnmarshalJSON(input []byte) error { RoundLength *uint64 `json:"roundLength"` MinBlockInterval *uint64 `json:"minBlockInterval"` FineValues []*math.HexOrDecimal256 `json:"fineValues"` + IsConsortium *bool `json:"isConsortium"` + AddressWhitelist []common.Address `json:"addressWhitelist"` } var dec DexconConfig if err := json.Unmarshal(input, &dec); err != nil { @@ -132,5 +138,11 @@ func (d *DexconConfig) UnmarshalJSON(input []byte) error { d.FineValues[k] = (*big.Int)(v) } } + if dec.IsConsortium != nil { + d.IsConsortium = *dec.IsConsortium + } + if dec.AddressWhitelist != nil { + d.AddressWhitelist = dec.AddressWhitelist + } return nil } -- cgit v1.2.3