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

@ -273,6 +273,14 @@ func (cr *fakeChainReader) ReadValidatorInformation(
) (*staking.ValidatorWrapper, error) { ) (*staking.ValidatorWrapper, error) {
return nil, nil 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( func (cr *fakeChainReader) ReadValidatorSnapshot(
addr common.Address, addr common.Address,
) (*staking.ValidatorSnapshot, error) { ) (*staking.ValidatorSnapshot, error) {

@ -282,7 +282,7 @@ func (hmy *Harmony) GetValidatorInformation(
addr common.Address, block *types.Block, addr common.Address, block *types.Block,
) (*staking.ValidatorRPCEnhanced, error) { ) (*staking.ValidatorRPCEnhanced, error) {
bc := hmy.BlockChain bc := hmy.BlockChain
wrapper, err := bc.ReadValidatorInformationAt(addr, block.Root()) wrapper, err := bc.ReadValidatorInformationAtRoot(addr, block.Root())
if err != nil { if err != nil {
s, _ := internalCommon.AddressToBech32(addr) s, _ := internalCommon.AddressToBech32(addr)
return nil, errors.Wrapf(err, "not found address in current state %s", s) 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( func (hmy *Harmony) GetDelegationsByValidatorAtBlock(
validator common.Address, block *types.Block, validator common.Address, block *types.Block,
) []*staking.Delegation { ) []*staking.Delegation {
wrapper, err := hmy.BlockChain.ReadValidatorInformationAt(validator, block.Root()) wrapper, err := hmy.BlockChain.ReadValidatorInformationAtRoot(validator, block.Root())
if err != nil || wrapper == nil { if err != nil || wrapper == nil {
return nil return nil
} }
@ -501,7 +501,7 @@ func (hmy *Harmony) GetDelegationsByDelegatorByBlock(
} }
for i := range delegationIndexes { for i := range delegationIndexes {
wrapper, err := hmy.BlockChain.ReadValidatorInformationAt( wrapper, err := hmy.BlockChain.ReadValidatorInformationAtRoot(
delegationIndexes[i].ValidatorAddress, block.Root(), delegationIndexes[i].ValidatorAddress, block.Root(),
) )
if err != nil || wrapper == nil { if err != nil || wrapper == nil {
@ -548,7 +548,7 @@ func (hmy *Harmony) GetUndelegationPayouts(
lockingPeriod := hmy.GetDelegationLockingPeriodInEpoch(undelegationPayoutBlock.Epoch()) lockingPeriod := hmy.GetDelegationLockingPeriodInEpoch(undelegationPayoutBlock.Epoch())
for _, validator := range hmy.GetAllValidatorAddresses() { 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 { if err != nil || wrapper == nil {
continue // Not a validator at this epoch or unable to fetch validator info because of pruned state. 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) return errors.New(msg)
} }
// Payout undelegated/unlocked tokens // Payout undelegated/unlocked tokens
lockPeriod := GetLockPeriodInEpoch(chain, header.Epoch())
noEarlyUnlock := chain.Config().IsNoEarlyUnlock(header.Epoch())
for _, validator := range validators { for _, validator := range validators {
wrapper, err := state.ValidatorWrapper(validator) wrapper, err := state.ValidatorWrapper(validator)
if err != nil { if err != nil {
@ -252,14 +254,14 @@ func payoutUndelegations(
"[Finalize] failed to get validator from state to finalize", "[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 { for i := range wrapper.Delegations {
delegation := &wrapper.Delegations[i] delegation := &wrapper.Delegations[i]
totalWithdraw := delegation.RemoveUnlockedUndelegations( totalWithdraw := delegation.RemoveUnlockedUndelegations(
header.Epoch(), wrapper.LastEpochInCommittee, lockPeriod, noEarlyUnlock, 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) countTrack[validator] = len(wrapper.Delegations)
} }

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

Loading…
Cancel
Save