forked from ethereum/go-ethereum
-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: write duration calculation in countdown as interface. add more inputs as function argument * feat: ExpTimeoutDuration * fix: three dots usage * feat: refine exp duration * feat: add exp timeout config and use it in countdown * feat: remove const countdown * feat: remove use of interface in countdown, use error * fix: countdown reset timer problem * fix: add default ExpTimeoutConfig for config
- Loading branch information
Showing
7 changed files
with
222 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// A countdown timer that will mostly be used by XDPoS v2 consensus engine | ||
package countdown | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"time" | ||
|
||
"github.com/XinFinOrg/XDPoSChain/core/types" | ||
) | ||
|
||
const maxExponentUpperbound uint8 = 32 | ||
|
||
type ExpTimeoutDuration struct { | ||
duration time.Duration | ||
base float64 | ||
maxExponent uint8 | ||
} | ||
|
||
func NewExpTimeoutDuration(duration time.Duration, base float64, maxExponent uint8) (*ExpTimeoutDuration, error) { | ||
d := &ExpTimeoutDuration{ | ||
duration: duration, | ||
base: base, | ||
maxExponent: maxExponent, | ||
} | ||
err := d.sanityCheck() | ||
return d, err | ||
} | ||
|
||
func (d *ExpTimeoutDuration) sanityCheck() error { | ||
if d.maxExponent >= maxExponentUpperbound { | ||
return fmt.Errorf("max_exponent (%d)= >= max_exponent_upperbound (%d)", d.maxExponent, maxExponentUpperbound) | ||
} | ||
if math.Pow(d.base, float64(d.maxExponent)) >= float64(math.MaxUint32) { | ||
return fmt.Errorf("base^max_exponent (%f^%d) should be less than 2^32", d.base, d.maxExponent) | ||
} | ||
return nil | ||
} | ||
|
||
// The inputs should be: currentRound, highestQuorumCert's round | ||
func (d *ExpTimeoutDuration) GetTimeoutDuration(currentRound, highestRound types.Round) time.Duration { | ||
power := float64(1) | ||
// below statement must be true, just to prevent negative result | ||
if highestRound < currentRound { | ||
exp := uint8(currentRound-highestRound) - 1 | ||
if exp > d.maxExponent { | ||
exp = d.maxExponent | ||
} | ||
power = math.Pow(d.base, float64(exp)) | ||
} | ||
return d.duration * time.Duration(power) | ||
} | ||
|
||
func (d *ExpTimeoutDuration) SetParams(duration time.Duration, base float64, maxExponent uint8) error { | ||
prevDuration := d.duration | ||
prevBase := d.base | ||
prevME := d.maxExponent | ||
|
||
d.duration = duration | ||
d.base = base | ||
d.maxExponent = maxExponent | ||
// if parameters are wrong, should remain instead of change or panic | ||
if err := d.sanityCheck(); err != nil { | ||
d.duration = prevDuration | ||
d.base = prevBase | ||
d.maxExponent = prevME | ||
return err | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package countdown | ||
|
||
import ( | ||
"math" | ||
"testing" | ||
"time" | ||
|
||
"github.com/XinFinOrg/XDPoSChain/core/types" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestExpDuration(t *testing.T) { | ||
base := float64(2.0) | ||
max_exponent := uint8(2) | ||
duration := time.Second * 59 | ||
helper, err := NewExpTimeoutDuration(duration, base, max_exponent) | ||
assert.Nil(t, err) | ||
// round 10 = 9+1, normal case, should be base | ||
currentRound := types.Round(10) | ||
highestQCRound := types.Round(9) | ||
result := helper.GetTimeoutDuration(currentRound, highestQCRound) | ||
assert.Equal(t, duration, result) | ||
|
||
// round 11 = 9+2, already 1 round timeout, should be base*exponent | ||
currentRound++ | ||
result = helper.GetTimeoutDuration(currentRound, highestQCRound) | ||
assert.Equal(t, duration*time.Duration(base), result) | ||
|
||
// round 12 = 9+3, already 2 rounds timeout, should be base*exponent^2 | ||
currentRound++ | ||
result = helper.GetTimeoutDuration(currentRound, highestQCRound) | ||
assert.Equal(t, duration*time.Duration(base)*time.Duration(base), result) | ||
|
||
// test SetParams | ||
duration++ | ||
max_exponent++ | ||
base++ | ||
helper.SetParams(duration, base, max_exponent) | ||
result = helper.GetTimeoutDuration(currentRound, highestQCRound) | ||
assert.Equal(t, duration*time.Duration(base)*time.Duration(base), result) | ||
// round 14 = 9+5, already 4 rounds timeout, but max_exponent=3, should be base*exponent^3 | ||
currentRound++ | ||
currentRound++ | ||
result = helper.GetTimeoutDuration(currentRound, highestQCRound) | ||
assert.Equal(t, duration*time.Duration(math.Pow(base, float64(3))), result) | ||
|
||
// extreme case | ||
helper.SetParams(duration, float64(0), uint8(0)) | ||
result = helper.GetTimeoutDuration(currentRound, highestQCRound) | ||
assert.Equal(t, duration, result) | ||
} | ||
|
||
func TestInvalidParameter(t *testing.T) { | ||
base := float64(2.0) | ||
max_exponent := uint8(32) | ||
duration := time.Second * 59 | ||
_, err := NewExpTimeoutDuration(duration, base, max_exponent) | ||
assert.Error(t, err) | ||
|
||
base = float64(3.0) | ||
max_exponent = uint8(21) | ||
duration = time.Second * 59 | ||
_, err = NewExpTimeoutDuration(duration, base, max_exponent) | ||
assert.Error(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.