mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Merge pull request #145 from XinFinOrg/mainnet_test
missing ValidatorMapping update.
This commit is contained in:
commit
f9fa3a8a07
13 changed files with 168 additions and 58 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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{}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<candidates.length;i++){
|
||||
if (getCandidateOwner(candidates[i])==_invalidMasternode){
|
||||
// logic to remove cap.
|
||||
candidateCount = candidateCount.sub(1);
|
||||
allMasternodes[count++] = candidates[i];
|
||||
delete candidates[i];
|
||||
delete validatorsState[candidates[i]];
|
||||
delete KYCString[_invalidMasternode];
|
||||
delete ownerToCandidate[_invalidMasternode];
|
||||
delete invalidKYCCount[_invalidMasternode];
|
||||
}
|
||||
}
|
||||
for(uint k=0;k<owners.length;k++){
|
||||
if (owners[k]==_invalidMasternode){
|
||||
delete owners[k];
|
||||
ownerCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit InvalidatedNode(_invalidMasternode,allMasternodes);
|
||||
}
|
||||
}
|
||||
|
||||
// invalidPercent : get votes against an owner in percentage.
|
||||
function invalidPercent(address _invalidCandidate) onlyValidCandidate(_invalidCandidate) view public returns(uint){
|
||||
address _invalidMasternode = getCandidateOwner(_invalidCandidate);
|
||||
return (invalidKYCCount[_invalidMasternode]*100/getOwnerCount());
|
||||
}
|
||||
|
||||
|
||||
// getOwnerCount : get count of total owners; accounts who own atleast one masternode.
|
||||
function getOwnerCount() view public returns (uint){
|
||||
return ownerCount;
|
||||
}
|
||||
|
||||
// getKYC : get KYC uploaded of the owner of the given masternode or the owner themselves
|
||||
function getLatestKYC(address _address) view public returns (string) {
|
||||
if(isCandidate(_address)){
|
||||
return KYCString[getCandidateOwner(_address)][KYCString[getCandidateOwner(_address)].length-1];
|
||||
}
|
||||
else{
|
||||
return KYCString[_address][KYCString[_address].length-1];
|
||||
}
|
||||
}
|
||||
|
||||
function getHashCount(address _address) view public returns(uint){
|
||||
return KYCString[_address].length;
|
||||
}
|
||||
|
||||
function withdraw(uint256 _blockNumber, uint _index) public onlyValidWithdraw(_blockNumber, _index) {
|
||||
uint256 cap = withdrawsState[msg.sender].caps[_blockNumber];
|
||||
delete withdrawsState[msg.sender].caps[_blockNumber];
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
package validator
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type Validator struct {
|
||||
|
|
@ -51,8 +52,8 @@ func DeployValidator(transactOpts *bind.TransactOpts, contractBackend bind.Contr
|
|||
// Min Voter Cap 10 XDC
|
||||
// 150 masternodes
|
||||
// Candidate Delay Withdraw 30 days = 1296000 blocks
|
||||
// Voter Delay Withdraw 2 days = 86400 blocks
|
||||
validatorAddr, _, _, err := contract.DeployXDCValidator(transactOpts, contractBackend, validatorAddress, caps, ownerAddress, minDeposit, minVoterCap, big.NewInt(150), big.NewInt(1296000), big.NewInt(86400))
|
||||
// Voter Delay Withdraw 10 days = 432000 blocks
|
||||
validatorAddr, _, _, err := contract.DeployXDCValidator(transactOpts, contractBackend, validatorAddress, caps, ownerAddress, minDeposit, minVoterCap, big.NewInt(18), big.NewInt(1296000), big.NewInt(432000))
|
||||
if err != nil {
|
||||
return validatorAddr, nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -519,6 +519,13 @@ func (bc *BlockChain) OrderStateAt(block *types.Block) (*tradingstate.TradingSta
|
|||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
XDCxState, err := XDCXService.GetEmptyTradingState()
|
||||
if err == nil {
|
||||
return XDCxState, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, errors.New("Get XDCx state fail")
|
||||
|
|
@ -2428,26 +2435,21 @@ func (bc *BlockChain) UpdateM1() error {
|
|||
}
|
||||
opts := new(bind.CallOpts)
|
||||
|
||||
// var candidates []common.Address
|
||||
// // get candidates from slot of stateDB
|
||||
// // if can't get anything, request from contracts
|
||||
// stateDB, err := bc.State()
|
||||
// if err != nil {
|
||||
|
||||
// candidates, err = validator.GetCandidates(opts)
|
||||
// if err != nil {
|
||||
|
||||
// return err
|
||||
// }
|
||||
// } else {
|
||||
|
||||
// candidates = state.GetCandidates(stateDB)
|
||||
|
||||
// }
|
||||
|
||||
candidates, err := validator.GetCandidates(opts)
|
||||
var candidates []common.Address
|
||||
// get candidates from slot of stateDB
|
||||
// if can't get anything, request from contracts
|
||||
stateDB, err := bc.State()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
candidates, err = validator.GetCandidates(opts)
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
candidates = state.GetCandidates(stateDB)
|
||||
|
||||
}
|
||||
|
||||
var ms []utils.Masternode
|
||||
|
|
@ -2487,7 +2489,7 @@ func (bc *BlockChain) UpdateM1() error {
|
|||
maxMasternodes = common.MaxMasternodes
|
||||
}
|
||||
if len(ms) > 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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue