diff --git a/XDCx/XDCx.go b/XDCx/XDCx.go index 9762bf6b50..2a8d9b299a 100644 --- a/XDCx/XDCx.go +++ b/XDCx/XDCx.go @@ -572,6 +572,9 @@ func (XDCx *XDCX) GetTradingState(block *types.Block, author common.Address) (*t } return tradingstate.New(root, XDCx.StateCache) } +func (XDCX *XDCX) GetEmptyTradingState() (*tradingstate.TradingStateDB, error) { + return tradingstate.New(tradingstate.EmptyRoot, XDCX.StateCache) +} func (XDCx *XDCX) GetStateCache() tradingstate.Database { return XDCx.StateCache diff --git a/common/constants.go b/common/constants.go index 2972277f2a..fdbbdfc742 100644 --- a/common/constants.go +++ b/common/constants.go @@ -24,7 +24,7 @@ const ( MergeSignRange = 15 RangeReturnSigner = 150 MinimunMinerBlockPerEpoch = 1 - IgnoreSignerCheckBlock = uint64(27307800) + OneYear = uint64(365 * 86400) LiquidateLendingTradeBlock = uint64(100) ) @@ -36,14 +36,14 @@ var TIPSigning = big.NewInt(3000000) var TIPRandomize = big.NewInt(3464000) var TIPIncreaseMasternodes = big.NewInt(5000000) // Upgrade MN Count at Block. -var TIPNoHalvingMNReward = big.NewInt(23779191) // hardfork no halving masternodes reward -var BlackListHFNumber = uint64(23779191) -var TIPXDCX = big.NewInt(23779191) -var TIPXDCXLending = big.NewInt(23779191) -var TIPXDCXCancellationFee = big.NewInt(23779191) -var TIPXDCXCancellationFeeTestnet = big.NewInt(23779191) +var TIPNoHalvingMNReward = big.NewInt(38383838) // hardfork no halving masternodes reward +var BlackListHFNumber = uint64(38383838) +var TIPXDCX = big.NewInt(38383838) +var TIPXDCXLending = big.NewInt(38383838) +var TIPXDCXCancellationFee = big.NewInt(38383838) +var TIPXDCXCancellationFeeTestnet = big.NewInt(38383838) -var TIPXDCXTestnet = big.NewInt(23779191) +var TIPXDCXTestnet = big.NewInt(38383838) var IsTestnet bool = false var StoreRewardFolder string var RollbackHash Hash @@ -71,9 +71,16 @@ var TRC21GasPrice = big.NewInt(250000000) var RateTopUp = big.NewInt(90) // 90% var BaseTopUp = big.NewInt(100) var BaseRecall = big.NewInt(100) -var TIPTRC21Fee = big.NewInt(23779191) -var TIPTRC21FeeTestnet = big.NewInt(23779191) +var TIPTRC21Fee = big.NewInt(38383838) +var TIPTRC21FeeTestnet = big.NewInt(38383838) var LimitTimeFinality = uint64(30) // limit in 30 block + +var IgnoreSignerCheckBlockArray = map[uint64]bool{ + uint64(1032300): true, + uint64(1033200): true, + uint64(27307800): true, + uint64(28270800): true, +} var Blacklist = map[Address]bool{ HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd"): true, HexToAddress("0x5ac26105b35ea8935be382863a70281ec7a985e9"): true, diff --git a/consensus/XDPoS/engines/engine_v1/engine.go b/consensus/XDPoS/engines/engine_v1/engine.go index 16c8bdb441..c5e7aaf0be 100644 --- a/consensus/XDPoS/engines/engine_v1/engine.go +++ b/consensus/XDPoS/engines/engine_v1/engine.go @@ -274,8 +274,8 @@ func (x *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty func (x *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header *types.Header, signers []common.Address) error { number := header.Number.Uint64() - // ignore signerCheck at checkpoint block 14458500 due to wrong snapshot at gap 14458495 - if number == common.IgnoreSignerCheckBlock { + // ignore signerCheck at checkpoint block. + if common.IgnoreSignerCheckBlockArray[number] { return nil } penPenalties := []common.Address{} diff --git a/consensus/XDPoS/utils/types.go b/consensus/XDPoS/utils/types.go index 754194c728..4f55973cfd 100644 --- a/consensus/XDPoS/utils/types.go +++ b/consensus/XDPoS/utils/types.go @@ -22,6 +22,7 @@ type Masternode struct { type TradingService interface { GetTradingStateRoot(block *types.Block, author common.Address) (common.Hash, error) GetTradingState(block *types.Block, author common.Address) (*tradingstate.TradingStateDB, error) + GetEmptyTradingState() (*tradingstate.TradingStateDB, error) HasTradingState(block *types.Block, author common.Address) bool GetStateCache() tradingstate.Database GetTriegc() *prque.Prque diff --git a/contracts/validator/contract/XDCValidator.sol b/contracts/validator/contract/XDCValidator.sol index 34d8b4e51b..0e67746a17 100644 --- a/contracts/validator/contract/XDCValidator.sol +++ b/contracts/validator/contract/XDCValidator.sol @@ -1,7 +1,9 @@ + pragma solidity ^0.4.21; import "./libs/SafeMath.sol"; + contract XDCValidator { using SafeMath for uint256; @@ -10,6 +12,8 @@ contract XDCValidator { event Propose(address _owner, address _candidate, uint256 _cap); event Resign(address _owner, address _candidate); event Withdraw(address _owner, uint256 _blockNumber, uint256 _cap); + event UploadedKYC(address _owner,string kycHash); + event InvalidatedNode(address _masternodeOwner, address[] _masternodes); struct ValidatorState { address owner; @@ -27,9 +31,18 @@ contract XDCValidator { mapping(address => ValidatorState) validatorsState; mapping(address => address[]) voters; + + // Mapping structures added for KYC feature. + mapping(address => string[]) public KYCString; + mapping(address => uint) public invalidKYCCount; + mapping(address => mapping(address => bool)) public hasVotedInvalid; + mapping(address => address[]) public ownerToCandidate; + address[] public owners; + address[] public candidates; uint256 public candidateCount = 0; + uint256 public ownerCount =0; uint256 public minCandidateCap; uint256 public minVoterCap; uint256 public maxValidatorNumber; @@ -43,10 +56,16 @@ contract XDCValidator { } modifier onlyValidVoterCap { + require(msg.value >= minVoterCap); _; } + modifier onlyKYCWhitelisted { + require(KYCString[msg.sender].length!=0 || ownerToCandidate[msg.sender].length>0); + _; + } + modifier onlyOwner(address _candidate) { require(validatorsState[_candidate].owner == msg.sender); _; @@ -99,7 +118,8 @@ contract XDCValidator { candidateWithdrawDelay = _candidateWithdrawDelay; voterWithdrawDelay = _voterWithdrawDelay; candidateCount = _candidates.length; - + owners.push(_firstOwner); + ownerCount++; for (uint256 i = 0; i < _candidates.length; i++) { candidates.push(_candidates[i]); validatorsState[_candidates[i]] = ValidatorState({ @@ -108,11 +128,20 @@ contract XDCValidator { cap: _caps[i] }); voters[_candidates[i]].push(_firstOwner); + ownerToCandidate[_firstOwner].push(_candidates[i]); validatorsState[_candidates[i]].voters[_firstOwner] = minCandidateCap; } } - function propose(address _candidate) external payable onlyValidCandidateCap onlyNotCandidate(_candidate) { + + // uploadKYC : anyone can upload a KYC; its not equivalent to becoming an owner. + function uploadKYC(string kychash) external { + KYCString[msg.sender].push(kychash); + emit UploadedKYC(msg.sender,kychash); + } + + // propose : any non-candidate who has uploaded its KYC can become an owner by proposing a candidate. + function propose(address _candidate) external payable onlyValidCandidateCap onlyKYCWhitelisted onlyNotCandidate(_candidate) { uint256 cap = validatorsState[_candidate].cap.add(msg.value); candidates.push(_candidate); validatorsState[_candidate] = ValidatorState({ @@ -122,6 +151,11 @@ contract XDCValidator { }); validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].add(msg.value); candidateCount = candidateCount.add(1); + if (ownerToCandidate[msg.sender].length ==0){ + owners.push(msg.sender); + ownerCount++; + } + ownerToCandidate[msg.sender].push(_candidate); voters[_candidate].push(msg.sender); emit Propose(msg.sender, _candidate, msg.value); } @@ -198,6 +232,67 @@ contract XDCValidator { emit Resign(msg.sender, _candidate); } + // voteInvalidKYC : any candidate can vote for invalid KYC i.e. a particular candidate's owner has uploaded a bad KYC. + // On securing 75% votes against an owner ( not candidate ), owner & all its candidates will lose their funds. + function voteInvalidKYC(address _invalidCandidate) onlyValidCandidate(msg.sender) onlyValidCandidate(_invalidCandidate) public { + address candidateOwner = getCandidateOwner(msg.sender); + address _invalidMasternode = getCandidateOwner(_invalidCandidate); + require(!hasVotedInvalid[candidateOwner][_invalidMasternode]); + hasVotedInvalid[candidateOwner][_invalidMasternode] = true; + invalidKYCCount[_invalidMasternode] += 1; + if( invalidKYCCount[_invalidMasternode]*100/getOwnerCount() >= 75 ){ + // 75% owners say that the KYC is invalid + address[] memory allMasternodes = new address[](candidates.length-1) ; + uint count=0; + for (uint i=0;i maxMasternodes { - err = engine.UpdateMasternodes(bc, bc.CurrentHeader(), ms[:common.MaxMasternodes]) + err = engine.UpdateMasternodes(bc, bc.CurrentHeader(), ms[:maxMasternodes]) } else { err = engine.UpdateMasternodes(bc, bc.CurrentHeader(), ms) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index e70ffe3ef8..9dc4b65117 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -18,13 +18,14 @@ package core import ( "fmt" - "github.com/XinFinOrg/XDPoSChain/core/rawdb" "math/big" "math/rand" "sync" "testing" "time" + "github.com/XinFinOrg/XDPoSChain/core/rawdb" + "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/consensus/ethash" "github.com/XinFinOrg/XDPoSChain/core/state" @@ -1323,7 +1324,7 @@ func TestLargeReorgTrieGC(t *testing.T) { } /* - Collection test for BlochsHashCache + Collection test for BlocksHashCache cases 1. When init new chain 2. when insertChain diff --git a/core/state/statedb_utils.go b/core/state/statedb_utils.go index 694bcdd127..4a0c9d45e6 100644 --- a/core/state/statedb_utils.go +++ b/core/state/statedb_utils.go @@ -73,8 +73,14 @@ var ( "withdrawsState": 0, "validatorsState": 1, "voters": 2, + "KYCString": 3, + "invalidKYCCount": 4, + "hasVotedInvalid": 5, + "ownerToCandidate": 6, + "owners": 7, "candidates": 8, "candidateCount": 9, + "ownerCount": 10, "minCandidateCap": 11, "minVoterCap": 12, "maxValidatorNumber": 13, diff --git a/eth/api.go b/eth/api.go index f6e4232356..9f12db9ec2 100644 --- a/eth/api.go +++ b/eth/api.go @@ -306,11 +306,7 @@ func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI { // DumpBlock retrieves the entire state of the database at a given block. func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { if blockNr == rpc.PendingBlockNumber { - // If we're dumping the pending state, we need to request - // both the pending block as well as the pending state from - // the miner and operate on those - _, stateDb := api.eth.miner.Pending() - return stateDb.RawDump(), nil + blockNr = rpc.LatestBlockNumber } var block *types.Block if blockNr == rpc.LatestBlockNumber { diff --git a/eth/api_backend.go b/eth/api_backend.go index e7c102f67e..9285afbac5 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -76,8 +76,7 @@ func (b *EthApiBackend) SetHead(number uint64) { func (b *EthApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { // Pending block is only known by the miner if blockNr == rpc.PendingBlockNumber { - block := b.eth.miner.PendingBlock() - return block.Header(), nil + blockNr = rpc.LatestBlockNumber } // Otherwise resolve and return the block if blockNr == rpc.LatestBlockNumber { @@ -89,8 +88,7 @@ func (b *EthApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNum func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) { // Pending block is only known by the miner if blockNr == rpc.PendingBlockNumber { - block := b.eth.miner.PendingBlock() - return block, nil + blockNr = rpc.LatestBlockNumber } // Otherwise resolve and return the block if blockNr == rpc.LatestBlockNumber { @@ -102,8 +100,7 @@ func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb func (b *EthApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) { // Pending state is only known by the miner if blockNr == rpc.PendingBlockNumber { - block, state := b.eth.miner.Pending() - return state, block.Header(), nil + blockNr = rpc.LatestBlockNumber } // Otherwise resolve the block number and return its state header, err := b.HeaderByNumber(ctx, blockNr) diff --git a/eth/api_tracer.go b/eth/api_tracer.go index 752a92bd3e..aa4d74b7b2 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -21,13 +21,14 @@ import ( "context" "errors" "fmt" - "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "io/ioutil" "math/big" "runtime" "sync" "time" + "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" + "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/core" @@ -99,7 +100,7 @@ func (api *PrivateDebugAPI) TraceChain(ctx context.Context, start, end rpc.Block switch start { case rpc.PendingBlockNumber: - from = api.eth.miner.PendingBlock() + from = api.eth.blockchain.CurrentBlock() case rpc.LatestBlockNumber: from = api.eth.blockchain.CurrentBlock() default: @@ -107,7 +108,7 @@ func (api *PrivateDebugAPI) TraceChain(ctx context.Context, start, end rpc.Block } switch end { case rpc.PendingBlockNumber: - to = api.eth.miner.PendingBlock() + to = api.eth.blockchain.CurrentBlock() case rpc.LatestBlockNumber: to = api.eth.blockchain.CurrentBlock() default: @@ -353,7 +354,7 @@ func (api *PrivateDebugAPI) TraceBlockByNumber(ctx context.Context, number rpc.B switch number { case rpc.PendingBlockNumber: - block = api.eth.miner.PendingBlock() + block = api.eth.blockchain.CurrentBlock() case rpc.LatestBlockNumber: block = api.eth.blockchain.CurrentBlock() default: @@ -514,7 +515,7 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (* break } if statedb, err = state.New(block.Root(), database); err == nil { - XDCxState, err = tradingstate.New(block.Root(), tradingstate.NewDatabase(api.eth.XDCX.GetLevelDB())) + XDCxState, err = api.eth.blockchain.OrderStateAt(block) if err == nil { break } diff --git a/params/version.go b/params/version.go index f9412f9e2a..c8d19d47bf 100644 --- a/params/version.go +++ b/params/version.go @@ -22,9 +22,9 @@ import ( const ( VersionMajor = 1 // Major version component of the current release - VersionMinor = 3 // Minor version component of the current release - VersionPatch = 0 // Patch version component of the current release - VersionMeta = "unstable" // Version metadata to append to the version string + VersionMinor = 4 // Minor version component of the current release + VersionPatch = 3 // Patch version component of the current release + VersionMeta = "stable" // Version metadata to append to the version string ) // Version holds the textual version string.