Avoid repeated state creation in validator reading

pull/3628/head
Rongjian Lan 4 years ago committed by Leo Chen
parent c345c4c44e
commit c64b90916d
  1. 19
      core/blockchain.go
  2. 8
      core/chain_makers.go
  3. 8
      hmy/staking.go
  4. 8
      internal/chain/engine.go
  5. 14
      shard/committee/assignment.go

@ -2280,18 +2280,29 @@ func (bc *BlockChain) ReadTxLookupEntry(txID common.Hash) (common.Hash, uint64,
return rawdb.ReadTxLookupEntry(bc.db, txID)
}
// ReadValidatorInformationAt reads staking
// ReadValidatorInformationAtRoot reads staking
// information of given validatorWrapper at a specific state root
func (bc *BlockChain) ReadValidatorInformationAt(
func (bc *BlockChain) ReadValidatorInformationAtRoot(
addr common.Address, root common.Hash,
) (*staking.ValidatorWrapper, error) {
state, err := bc.StateAt(root)
if err != nil || state == nil {
return nil, errors.Wrapf(err, "at root: %s", root.Hex())
}
return bc.ReadValidatorInformationAtState(addr, state)
}
// ReadValidatorInformationAtState reads staking
// information of given validatorWrapper at a specific state root
func (bc *BlockChain) ReadValidatorInformationAtState(
addr common.Address, state *state.DB,
) (*staking.ValidatorWrapper, error) {
if state == nil {
return nil, errors.New("empty state")
}
wrapper, err := state.ValidatorWrapper(addr)
if err != nil {
return nil, errors.Wrapf(err, "at root: %s", root.Hex())
return nil, err
}
return wrapper, nil
}
@ -2300,7 +2311,7 @@ func (bc *BlockChain) ReadValidatorInformationAt(
func (bc *BlockChain) ReadValidatorInformation(
addr common.Address,
) (*staking.ValidatorWrapper, error) {
return bc.ReadValidatorInformationAt(addr, bc.CurrentBlock().Root())
return bc.ReadValidatorInformationAtRoot(addr, bc.CurrentBlock().Root())
}
// ReadValidatorSnapshotAtEpoch reads the snapshot

@ -273,6 +273,14 @@ func (cr *fakeChainReader) ReadValidatorInformation(
) (*staking.ValidatorWrapper, error) {
return nil, nil
}
func (cr *fakeChainReader) ReadValidatorInformationAtState(
addr common.Address, state *state.DB,
) (*staking.ValidatorWrapper, error) {
return nil, nil
}
func (cr *fakeChainReader) StateAt(root common.Hash) (*state.DB, error) {
return nil, nil
}
func (cr *fakeChainReader) ReadValidatorSnapshot(
addr common.Address,
) (*staking.ValidatorSnapshot, error) {

@ -282,7 +282,7 @@ func (hmy *Harmony) GetValidatorInformation(
addr common.Address, block *types.Block,
) (*staking.ValidatorRPCEnhanced, error) {
bc := hmy.BlockChain
wrapper, err := bc.ReadValidatorInformationAt(addr, block.Root())
wrapper, err := bc.ReadValidatorInformationAtRoot(addr, block.Root())
if err != nil {
s, _ := internalCommon.AddressToBech32(addr)
return nil, errors.Wrapf(err, "not found address in current state %s", s)
@ -469,7 +469,7 @@ func (hmy *Harmony) GetDelegationsByValidator(validator common.Address) []*staki
func (hmy *Harmony) GetDelegationsByValidatorAtBlock(
validator common.Address, block *types.Block,
) []*staking.Delegation {
wrapper, err := hmy.BlockChain.ReadValidatorInformationAt(validator, block.Root())
wrapper, err := hmy.BlockChain.ReadValidatorInformationAtRoot(validator, block.Root())
if err != nil || wrapper == nil {
return nil
}
@ -501,7 +501,7 @@ func (hmy *Harmony) GetDelegationsByDelegatorByBlock(
}
for i := range delegationIndexes {
wrapper, err := hmy.BlockChain.ReadValidatorInformationAt(
wrapper, err := hmy.BlockChain.ReadValidatorInformationAtRoot(
delegationIndexes[i].ValidatorAddress, block.Root(),
)
if err != nil || wrapper == nil {
@ -548,7 +548,7 @@ func (hmy *Harmony) GetUndelegationPayouts(
lockingPeriod := hmy.GetDelegationLockingPeriodInEpoch(undelegationPayoutBlock.Epoch())
for _, validator := range hmy.GetAllValidatorAddresses() {
wrapper, err := hmy.BlockChain.ReadValidatorInformationAt(validator, undelegationPayoutBlock.Root())
wrapper, err := hmy.BlockChain.ReadValidatorInformationAtRoot(validator, undelegationPayoutBlock.Root())
if err != nil || wrapper == nil {
continue // Not a validator at this epoch or unable to fetch validator info because of pruned state.
}

@ -245,6 +245,8 @@ func payoutUndelegations(
return errors.New(msg)
}
// Payout undelegated/unlocked tokens
lockPeriod := GetLockPeriodInEpoch(chain, header.Epoch())
noEarlyUnlock := chain.Config().IsNoEarlyUnlock(header.Epoch())
for _, validator := range validators {
wrapper, err := state.ValidatorWrapper(validator)
if err != nil {
@ -252,14 +254,14 @@ func payoutUndelegations(
"[Finalize] failed to get validator from state to finalize",
)
}
lockPeriod := GetLockPeriodInEpoch(chain, header.Epoch())
noEarlyUnlock := chain.Config().IsNoEarlyUnlock(header.Epoch())
for i := range wrapper.Delegations {
delegation := &wrapper.Delegations[i]
totalWithdraw := delegation.RemoveUnlockedUndelegations(
header.Epoch(), wrapper.LastEpochInCommittee, lockPeriod, noEarlyUnlock,
)
state.AddBalance(delegation.DelegatorAddress, totalWithdraw)
if totalWithdraw.Sign() != 0 {
state.AddBalance(delegation.DelegatorAddress, totalWithdraw)
}
}
countTrack[validator] = len(wrapper.Delegations)
}

@ -4,6 +4,8 @@ import (
"encoding/json"
"math/big"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/crypto/bls"
"github.com/ethereum/go-ethereum/common"
@ -38,7 +40,11 @@ type Reader interface {
// StakingCandidatesReader ..
type StakingCandidatesReader interface {
CurrentBlock() *types.Block
StateAt(root common.Hash) (*state.DB, error)
ReadValidatorInformation(addr common.Address) (*staking.ValidatorWrapper, error)
ReadValidatorInformationAtState(
addr common.Address, state *state.DB,
) (*staking.ValidatorWrapper, error)
ReadValidatorSnapshot(addr common.Address) (*staking.ValidatorSnapshot, error)
ValidatorCandidates() []common.Address
}
@ -145,11 +151,15 @@ func prepareOrders(
blsKeys[pubKey] = struct{}{}
}
state, err := stakedReader.StateAt(stakedReader.CurrentBlock().Root())
if err != nil || state == nil {
return nil, errors.Wrapf(err, "not state found at root: %s", stakedReader.CurrentBlock().Root().Hex())
}
for i := range candidates {
// TODO: reading validator wrapper from DB could be a bottle net when there are hundreds of validators
// with thousands of delegator data.
validator, err := stakedReader.ReadValidatorInformation(
candidates[i],
validator, err := stakedReader.ReadValidatorInformationAtState(
candidates[i], state,
)
if err != nil {
return nil, err

Loading…
Cancel
Save