Skip to content

Commit

Permalink
Merge branch 'change_stateDB_implementation' of https://github.com/ko…
Browse files Browse the repository at this point in the history
…seoyoung/iotex-core into change_stateDB_implementation
  • Loading branch information
koseoyoung committed Feb 6, 2020
2 parents ff89bc9 + a8a7ff2 commit 20c7f0f
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 27 deletions.
30 changes: 16 additions & 14 deletions action/protocol/poll/nativestaking.go
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand Down Expand Up @@ -32,7 +32,7 @@ var (

type (
// ReadContract defines a callback function to read contract
ReadContract func(context.Context, string, uint64, time.Time, []byte) ([]byte, error)
ReadContract func(context.Context, string, []byte, bool) ([]byte, error)
// NativeStaking represents native staking struct
NativeStaking struct {
readContract ReadContract
Expand Down Expand Up @@ -76,7 +76,7 @@ func NewNativeStaking(readContract ReadContract) (*NativeStaking, error) {
}

// Votes returns the votes on height
func (ns *NativeStaking) Votes(ctx context.Context, height uint64, ts time.Time) (*VoteTally, error) {
func (ns *NativeStaking) Votes(ctx context.Context, ts time.Time, correctGas bool) (*VoteTally, error) {
if ns.contract == "" {
return nil, ErrNoData
}
Expand All @@ -90,47 +90,48 @@ func (ns *NativeStaking) Votes(ctx context.Context, height uint64, ts time.Time)
limit := big.NewInt(256)

for {
vote, err := ns.readBuckets(ctx, prevIndex, limit, height, ts)
vote, index, err := ns.readBuckets(ctx, prevIndex, limit, correctGas)
log.L().Debug("Read native buckets from contract", zap.Int("size", len(vote)))
if err == ErrEndOfData {
// all data been read
break
}
if err != nil {
log.L().Error(" read native staking contract", zap.Error(err))
return nil, err
}
votes.tally(vote, ts)
if len(vote) < int(limit.Int64()) {
// all data been read
break
}
prevIndex.Add(prevIndex, limit)
prevIndex = index
}
return &votes, nil
}

func (ns *NativeStaking) readBuckets(ctx context.Context, prevIndx, limit *big.Int, height uint64, ts time.Time) ([]*types.Bucket, error) {
func (ns *NativeStaking) readBuckets(ctx context.Context, prevIndx, limit *big.Int, correctGas bool) ([]*types.Bucket, *big.Int, error) {
data, err := ns.abi.Pack("getActivePyggs", prevIndx, limit)
if err != nil {
return nil, err
return nil, nil, err
}

data, err = ns.readContract(ctx, ns.contract, height, ts, data)
data, err = ns.readContract(ctx, ns.contract, data, correctGas)
if err != nil {
return nil, err
return nil, nil, err
}

// decode the contract read result
pygg := &pygg{}
if err = ns.abi.Unpack(pygg, "getActivePyggs", data); err != nil {
if err.Error() == "abi: unmarshalling empty output" {
// no data in contract (one possible reason is that contract does not exist yet)
return nil, ErrNoData
return nil, nil, ErrNoData
}
return nil, err
return nil, nil, err
}
if len(pygg.CanNames) == 0 {
return nil, ErrEndOfData
return nil, nil, ErrEndOfData
}

buckets := make([]*types.Bucket, len(pygg.CanNames))
Expand All @@ -144,10 +145,11 @@ func (ns *NativeStaking) readBuckets(ctx context.Context, prevIndx, limit *big.I
pygg.Decays[i],
)
if err != nil {
return nil, err
return nil, nil, err
}
}
return buckets, nil
// last one of returned indexes should be used as starting index for next query
return buckets, pygg.Indexes[len(pygg.Indexes)-1], nil
}

// SetContract sets the contract address
Expand Down
48 changes: 46 additions & 2 deletions action/protocol/poll/nativestaking_test.go
@@ -1,3 +1,9 @@
// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package poll

import (
Expand Down Expand Up @@ -39,7 +45,7 @@ func TestStaking(t *testing.T) {

ns, err := NewNativeStaking(nil)
require.Error(err)
ns, err = NewNativeStaking(func(context.Context, string, uint64, time.Time, []byte) ([]byte, error) {
ns, err = NewNativeStaking(func(context.Context, string, []byte, bool) ([]byte, error) {
return nil, nil
})
ns.SetContract("io1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqd39ym7")
Expand All @@ -66,7 +72,7 @@ func TestStaking(t *testing.T) {
)
}

tallies := VoteTally{
tallies := &VoteTally{
Candidates: make(map[[12]byte]*state.Candidate),
Buckets: make([]*types.Bucket, 0),
}
Expand All @@ -82,6 +88,44 @@ func TestStaking(t *testing.T) {
}
}
require.Equal(len(buckets), len(tallies.Buckets))
for i := range buckets {
require.Equal(buckets[i], tallies.Buckets[i])
}

// merge with existing data
cand := state.CandidateList{
&state.Candidate{
CanName: []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Votes: big.NewInt(111),
},
&state.Candidate{
CanName: []byte{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Votes: big.NewInt(111),
},
&state.Candidate{
CanName: []byte{107, 111, 118, 97, 110, 114, 111, 98, 111, 116, 50, 56},
Votes: big.NewInt(111),
},
&state.Candidate{
CanName: []byte{107, 111, 118, 97, 110, 114, 111, 98, 111, 116, 50, 55},
Votes: big.NewInt(111),
},
}

amount = big.NewInt(unit.Iotx)
sc := &stakingCommittee{
nativeStaking: ns,
scoreThreshold: amount.Mul(amount, big.NewInt(200)),
}

newCand := sc.mergeCandidates(cand, tallies, time.Now())
require.Equal(2, len(newCand))
for i := range newCand {
name := cand[i].CanName
require.Equal(name, newCand[i].CanName)
cand[i].Votes.Add(cand[i].Votes, tallies.Candidates[to12Bytes(name)].Votes)
require.Equal(cand[i].Votes, newCand[i].Votes)
}

// test empty data from contract
require.NoError(ns.abi.Unpack(pygg, "getActivePyggs", empty))
Expand Down
2 changes: 1 addition & 1 deletion action/protocol/poll/protocol_test.go
Expand Up @@ -31,7 +31,7 @@ func TestNewProtocol(t *testing.T) {
cfg.Consensus.Scheme = config.RollDPoSScheme
p, err := NewProtocol(
cfg,
func(context.Context, string, uint64, time.Time, []byte) ([]byte, error) { return nil, nil },
func(context.Context, string, []byte, bool) ([]byte, error) { return nil, nil },
nil,
nil,
nil,
Expand Down
4 changes: 2 additions & 2 deletions action/protocol/poll/staking_committee.go
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand Down Expand Up @@ -196,7 +196,7 @@ func (sc *stakingCommittee) CalculateCandidatesByHeight(ctx context.Context, hei
}

// TODO: extract tip info inside of Votes function
nativeVotes, err := sc.nativeStaking.Votes(ctx, bcCtx.Tip.Height, bcCtx.Tip.Timestamp)
nativeVotes, err := sc.nativeStaking.Votes(ctx, bcCtx.Tip.Timestamp, hu.IsPost(config.Daytona, height))
if err == ErrNoData {
// no native staking data
return sc.filterCandidates(cand), nil
Expand Down
2 changes: 1 addition & 1 deletion action/protocol/poll/staking_committee_test.go
Expand Up @@ -114,7 +114,7 @@ func initConstructStakingCommittee(ctrl *gomock.Controller) (Protocol, context.C
p, err := NewStakingCommittee(
committee,
gs,
func(ctx context.Context, contract string, height uint64, ts time.Time, params []byte) ([]byte, error) {
func(context.Context, string, []byte, bool) ([]byte, error) {
return nil, nil
},
cfg.Genesis.NativeStakingContractAddress,
Expand Down
5 changes: 4 additions & 1 deletion blockchain/genesis/genesis.go
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand Down Expand Up @@ -53,6 +53,7 @@ func defaultConfig() Genesis {
BeringBlockHeight: 1512001,
CookBlockHeight: 1641601,
DardanellesBlockHeight: 1816201,
DaytonaBlockHeight: 3238921,
EnglishBlockHeight: 3363481,
},
Account: Account{
Expand Down Expand Up @@ -136,6 +137,8 @@ type (
CookBlockHeight uint64 `yaml:"cookHeight"`
// DardanellesBlockHeight is the start height of 5s block internal
DardanellesBlockHeight uint64 `yaml:"dardanellesHeight"`
// DaytonaBlockHeight is the height to fix low gas for read native staking contract
DaytonaBlockHeight uint64 `yaml:"daytonaBlockHeight"`
// EnglishBlockHeight is the start height of kick-out for slashing
EnglishBlockHeight uint64 `yaml:englishHeight`
}
Expand Down
8 changes: 6 additions & 2 deletions chainservice/chainservice.go
Expand Up @@ -209,8 +209,12 @@ func New(
copts = append(copts, consensus.WithRollDPoSProtocol(rDPoSProtocol))
pollProtocol, err = poll.NewProtocol(
cfg,
func(ctx context.Context, contract string, height uint64, ts time.Time, params []byte) ([]byte, error) {
ex, err := action.NewExecution(contract, 1, big.NewInt(0), 1000000, big.NewInt(0), params)
func(ctx context.Context, contract string, params []byte, correctGas bool) ([]byte, error) {
gasLimit := uint64(1000000)
if correctGas {
gasLimit *= 10
}
ex, err := action.NewExecution(contract, 1, big.NewInt(0), gasLimit, big.NewInt(0), params)
if err != nil {
return nil, err
}
Expand Down
15 changes: 14 additions & 1 deletion config/heightupgrade.go
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX
// Copyright (c) 2020 IoTeX
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand All @@ -19,6 +19,7 @@ const (
Bering
Cook
Dardanelles
Daytona
English
)

Expand All @@ -27,12 +28,18 @@ type (
HeightName int

// HeightUpgrade lists heights at which certain fixes take effect
// prior to Dardanelles, each epoch consists of 360 sub-epochs
// so height = 360k + 1
// starting Dardanelles, each epoch consists of 720 sub-epochs
// however, DardanellesHeight is set to 360(2k + 1) + 1 (instead of 720k + 1)
// so height afterwards must be set to 360(2k + 1) + 1
HeightUpgrade struct {
pacificHeight uint64
aleutianHeight uint64
beringHeight uint64
cookHeight uint64
dardanellesHeight uint64
daytonaHeight uint64
englishHeight uint64
}
)
Expand All @@ -45,6 +52,7 @@ func NewHeightUpgrade(cfg *genesis.Genesis) HeightUpgrade {
cfg.BeringBlockHeight,
cfg.CookBlockHeight,
cfg.DardanellesBlockHeight,
cfg.DaytonaBlockHeight,
cfg.EnglishBlockHeight,
}
}
Expand All @@ -63,6 +71,8 @@ func (hu *HeightUpgrade) IsPost(name HeightName, height uint64) bool {
h = hu.cookHeight
case Dardanelles:
h = hu.dardanellesHeight
case Daytona:
h = hu.daytonaHeight
case English:
h = hu.englishHeight
default:
Expand Down Expand Up @@ -91,5 +101,8 @@ func (hu *HeightUpgrade) CookBlockHeight() uint64 { return hu.cookHeight }
// DardanellesBlockHeight returns the dardanelles height
func (hu *HeightUpgrade) DardanellesBlockHeight() uint64 { return hu.dardanellesHeight }

// DaytonaBlockHeight returns the daytona height
func (hu *HeightUpgrade) DaytonaBlockHeight() uint64 { return hu.daytonaHeight }

// EnglishBlockHeight returns the english height
func (hu *HeightUpgrade) EnglishBlockHeight() uint64 { return hu.englishHeight }
9 changes: 6 additions & 3 deletions config/heightupgrade_test.go
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX
// Copyright (c) 2020 IoTeX
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand All @@ -20,7 +20,8 @@ func TestNewHeightChange(t *testing.T) {
require.Equal(2, Bering)
require.Equal(3, Cook)
require.Equal(4, Dardanelles)
require.Equal(5, English)
require.Equal(5, Daytona)
require.Equal(6, English)

cfg := Default
cfg.Genesis.PacificBlockHeight = uint64(432001)
Expand All @@ -36,6 +37,8 @@ func TestNewHeightChange(t *testing.T) {
require.True(hu.IsPost(Cook, uint64(1641601)))
require.True(hu.IsPre(Dardanelles, uint64(1816200)))
require.True(hu.IsPost(Dardanelles, uint64(1816201)))
require.True(hu.IsPre(Daytona, uint64(3238920)))
require.True(hu.IsPost(Daytona, uint64(3238921)))
require.True(hu.IsPre(English, uint64(3363480)))
require.True(hu.IsPost(English, uint64(3363481)))
require.Panics(func() {
Expand All @@ -47,6 +50,6 @@ func TestNewHeightChange(t *testing.T) {
require.Equal(hu.BeringBlockHeight(), uint64(1512001))
require.Equal(hu.CookBlockHeight(), uint64(1641601))
require.Equal(hu.DardanellesBlockHeight(), uint64(1816201))
require.Equal(hu.DaytonaBlockHeight(), uint64(3238921))
require.Equal(hu.EnglishBlockHeight(), uint64(3363481))

}
3 changes: 3 additions & 0 deletions e2etest/rewarding_test.go
Expand Up @@ -65,6 +65,8 @@ func TestBlockReward(t *testing.T) {
testDBPath := testDBFile.Name()
testIndexFile, _ := ioutil.TempFile(os.TempDir(), "index")
testIndexPath := testIndexFile.Name()
testConsensusFile, _ := ioutil.TempFile(os.TempDir(), "cons")
testConsensusPath := testConsensusFile.Name()

cfg := config.Default
cfg.Consensus.Scheme = config.RollDPoSScheme
Expand All @@ -82,6 +84,7 @@ func TestBlockReward(t *testing.T) {
cfg.Consensus.RollDPoS.FSM.AcceptProposalEndorsementTTL = 300 * time.Millisecond
cfg.Consensus.RollDPoS.FSM.AcceptLockEndorsementTTL = 300 * time.Millisecond
cfg.Consensus.RollDPoS.FSM.CommitTTL = 100 * time.Millisecond
cfg.Consensus.RollDPoS.ConsensusDBPath = testConsensusPath
cfg.Genesis.EnableGravityChainVoting = true
cfg.Chain.ProducerPrivKey = identityset.PrivateKey(0).HexString()
cfg.Chain.TrieDBPath = testTriePath
Expand Down

0 comments on commit 20c7f0f

Please sign in to comment.