From 5e30a1686f8a049c27d10d21cca1b7b5aee18f70 Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Sun, 4 Aug 2019 13:39:30 +0800 Subject: core: consider reset round when getting config state Previous config snapshot is determined as follows, for round n: Return the snapshot state of round (n - ConfigRoundShift) However this may cause the system to stuck at a particular round if the DKG for the next round continues to fail (maybe due to node failure). To fix this, instead of using the simple logic above, we consider the reset rounds as a normal round, and use the snapshot of the reset rounds as config. Thus we could gradually push out the broken nodes from nodeset. The snapshot is now determined as follows, for round n: If resetCount < ConfigRoundShift Return the snapshot state of round (n - ConfigRoundShift) Else Reutrn the stateshot state of (n + resetCount - ConfigRoundShift) --- core/governance.go | 2 +- core/vm/oracle_contracts.go | 2 +- core/vm/utils.go | 40 +++++++++++++++++++++++++++++++++------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/core/governance.go b/core/governance.go index 8bad0ca98..8cfed5e13 100644 --- a/core/governance.go +++ b/core/governance.go @@ -110,7 +110,7 @@ func (g *Governance) GetStateForDKGAtRound(round uint64) (*vm.GovernanceState, e if round == dkgRound { return gs, nil } - return g.util.GetStateAtRound(round) + return g.util.GetRoundState(round) } func (g *Governance) CRSRound() uint64 { diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go index a2c7d7814..e1408d8d2 100644 --- a/core/vm/oracle_contracts.go +++ b/core/vm/oracle_contracts.go @@ -2172,7 +2172,7 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) { g.fineFailStopDKG(tsigThreshold) // Update CRS. - state, err := g.util.GetStateAtRound(round.Uint64()) + state, err := g.util.GetRoundState(round.Uint64()) if err != nil { return nil, errExecutionReverted } diff --git a/core/vm/utils.go b/core/vm/utils.go index 0cc6343cc..5ccc47867 100644 --- a/core/vm/utils.go +++ b/core/vm/utils.go @@ -28,7 +28,7 @@ func (g GovUtil) GetRoundHeight(round uint64) uint64 { return gs.RoundHeight(big.NewInt(int64(round))).Uint64() } -func (g GovUtil) GetStateAtRound(round uint64) (*GovernanceState, error) { +func (g GovUtil) GetRoundState(round uint64) (*GovernanceState, error) { height := g.GetRoundHeight(round) if round != 0 && height == 0 { @@ -44,12 +44,38 @@ func (g GovUtil) GetStateAtRound(round uint64) (*GovernanceState, error) { } func (g GovUtil) GetConfigState(round uint64) (*GovernanceState, error) { + headState, err := g.Intf.GetHeadGovState() + if err != nil { + return nil, err + } + if round < dexCore.ConfigRoundShift { - round = 0 - } else { - round -= dexCore.ConfigRoundShift + return g.GetRoundState(0) } - return g.GetStateAtRound(round) + + resetCount := headState.DKGResetCount(new(big.Int).SetUint64(round)).Uint64() + + // If we are resetting more round then ConfigRoundShift, we need to get the + // state of (resetCount - ConfigRoundShift) instead. + if resetCount >= dexCore.ConfigRoundShift { + shift := resetCount - dexCore.ConfigRoundShift + + prevConfigState, err := g.GetConfigState(round - 1) + if err != nil { + log.Error("Failed to get previous round config state", "round", round-1) + return nil, err + } + + height := g.GetRoundHeight(round-1) + shift*prevConfigState.RoundLength().Uint64() + s, err := g.Intf.StateAt(height) + if err != nil { + log.Error("Failed to get state", "height", height) + return nil, err + } + return &GovernanceState{StateDB: s}, nil + } + + return g.GetRoundState(round - dexCore.ConfigRoundShift) } func (g *GovUtil) CRSRound() uint64 { @@ -62,7 +88,7 @@ func (g *GovUtil) CRSRound() uint64 { func (g GovUtil) CRS(round uint64) common.Hash { if round <= dexCore.DKGDelayRound { - s, err := g.GetStateAtRound(0) + s, err := g.GetRoundState(0) if err != nil { return common.Hash{} } @@ -83,7 +109,7 @@ func (g GovUtil) CRS(round uint64) common.Hash { return common.Hash{} } } else { - s, err = g.GetStateAtRound(round) + s, err = g.GetRoundState(round) if err != nil { return common.Hash{} } -- cgit