Merge pull request #1870 from rlan35/staking_tx

Synchronize shard chains with beacon chain after stakingEpoch. Add PreStakingEpoch
pull/1872/head
Rongjian Lan 5 years ago committed by GitHub
commit 9cd64ef00a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      block/factory/factory.go
  2. 2
      cmd/client/txgen/main.go
  3. 11
      cmd/harmony/main.go
  4. 12
      cmd/staking/root.go
  5. 133
      consensus/consensus_service.go
  6. 1
      consensus/consensus_v2.go
  7. 8
      consensus/quorum/one-node-staked-vote.go
  8. 35
      core/blockchain.go
  9. 1
      core/state_transition.go
  10. 4
      internal/chain/engine.go
  11. 51
      internal/params/config.go
  12. 12
      internal/utils/utils.go
  13. 28
      node/node.go
  14. 2
      node/node_genesis.go
  15. 54
      node/node_handler.go
  16. 27
      node/node_newblock.go
  17. 68
      node/worker/worker.go
  18. 80
      shard/committee/assignment.go
  19. 10
      shard/shard_state.go
  20. 29
      test/configs/local-resharding.txt

@ -30,11 +30,11 @@ func NewFactory(chainConfig *params.ChainConfig) Factory {
func (f *factory) NewHeader(epoch *big.Int) *block.Header { func (f *factory) NewHeader(epoch *big.Int) *block.Header {
var impl blockif.Header var impl blockif.Header
switch { switch {
case epoch.Cmp(f.chainConfig.StakingEpoch) >= 0: case f.chainConfig.IsPreStaking(epoch):
impl = v3.NewHeader() impl = v3.NewHeader()
case epoch.Cmp(f.chainConfig.CrossLinkEpoch) >= 0: case f.chainConfig.IsCrossLink(epoch):
impl = v2.NewHeader() impl = v2.NewHeader()
case epoch.Cmp(f.chainConfig.CrossTxEpoch) >= 0: case f.chainConfig.IsCrossTx(epoch):
impl = v1.NewHeader() impl = v1.NewHeader()
default: default:
impl = v0.NewHeader() impl = v0.NewHeader()

@ -219,7 +219,7 @@ syncLoop:
Msg("Error when adding new block") Msg("Error when adding new block")
} }
stateMutex.Lock() stateMutex.Lock()
if err := txGen.Worker.UpdateCurrent(block.Coinbase()); err != nil { if err := txGen.Worker.UpdateCurrent(); err != nil {
utils.Logger().Warn().Err(err).Msg("(*Worker).UpdateCurrent failed") utils.Logger().Warn().Err(err).Msg("(*Worker).UpdateCurrent failed")
} }
stateMutex.Unlock() stateMutex.Unlock()

@ -195,6 +195,7 @@ func setupInitialAccount() (isLeader bool) {
pubKey := setupConsensusKey(nodeconfig.GetDefaultConfig()) pubKey := setupConsensusKey(nodeconfig.GetDefaultConfig())
reshardingEpoch := genesisShardingConfig.ReshardingEpoch() reshardingEpoch := genesisShardingConfig.ReshardingEpoch()
// TODO: after staking, what if the FN validator uses the old bls pub keys?
if reshardingEpoch != nil && len(reshardingEpoch) > 0 { if reshardingEpoch != nil && len(reshardingEpoch) > 0 {
for _, epoch := range reshardingEpoch { for _, epoch := range reshardingEpoch {
config := shard.Schedule.InstanceForEpoch(epoch) config := shard.Schedule.InstanceForEpoch(epoch)
@ -208,12 +209,14 @@ func setupInitialAccount() (isLeader bool) {
} }
if initialAccount == nil { if initialAccount == nil {
fmt.Fprintf(os.Stderr, "ERROR cannot find your BLS key in the genesis/FN tables: %s\n", pubKey.SerializeToHexStr()) initialAccount.ShardID = uint32(*shardID)
os.Exit(100) initialAccount.BlsPublicKey = pubKey.SerializeToHexStr()
blsAddressBytes := pubKey.GetAddress()
initialAccount.Address = hex.EncodeToString(blsAddressBytes[:])
} else {
fmt.Printf("My Genesis Account: %v\n", *initialAccount)
} }
fmt.Printf("My Genesis Account: %v\n", *initialAccount)
return isLeader return isLeader
} }

@ -56,11 +56,15 @@ var (
rate = "0.15" rate = "0.15"
testAccounts = []string{ testAccounts = []string{
"one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", "one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7",
"one12fuf7x9rgtdgqg7vgq0962c556m3p7afsxgvll"} "one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg",
"one1r4zyyjqrulf935a479sgqlpa78kz7zlcg2jfen",
"one1p7ht2d4kl8ve7a8jxw746yfnx4wnfxtp8jqxwe"}
testBLSPubKeys = []string{ testBLSPubKeys = []string{
"65f55eb3052f9e9f632b2923be594ba77c55543f5c58ee1454b9cfd658d25e06373b0f7d42a19c84768139ea294f6204", "678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c",
"02c8ff0b88f313717bc3a627d2f8bb172ba3ad3bb9ba3ecb8eed4b7c878653d3d4faf769876c528b73f343967f74a917"} "a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100",
"fc4b9c535ee91f015efff3f32fbb9d32cdd9bfc8a837bb3eee89b8fff653c7af2050a4e147ebe5c7233dc2d5df06ee0a",
"ca86e551ee42adaaa6477322d7db869d3e203c00d7b86c82ebee629ad79cb6d57b8f3db28336778ec2180e56a8e07296"}
) )
func (s *staker) run(cmd *cobra.Command, args []string) error { func (s *staker) run(cmd *cobra.Command, args []string) error {

@ -428,15 +428,29 @@ func (consensus *Consensus) getLeaderPubKeyFromCoinbase(header *block.Header) (*
) )
} }
committerKey := new(bls.PublicKey) committerKey := new(bls.PublicKey)
isStaking := consensus.ChainReader.Config().IsStaking(header.Epoch())
for _, member := range committee.Slots { for _, member := range committee.Slots {
if member.EcdsaAddress == header.Coinbase() { if isStaking {
err := member.BlsPublicKey.ToLibBLSPublicKey(committerKey) // After staking the coinbase address will be the address of bls public key
if err != nil { if utils.GetAddressFromBlsPubKeyBytes(member.BlsPublicKey[:]) == header.Coinbase() {
return nil, ctxerror.New("cannot convert BLS public key", err := member.BlsPublicKey.ToLibBLSPublicKey(committerKey)
"blsPublicKey", member.BlsPublicKey, if err != nil {
"coinbaseAddr", header.Coinbase()).WithCause(err) return nil, ctxerror.New("cannot convert BLS public key",
"blsPublicKey", member.BlsPublicKey,
"coinbaseAddr", header.Coinbase()).WithCause(err)
}
return committerKey, nil
}
} else {
if member.EcdsaAddress == header.Coinbase() {
err := member.BlsPublicKey.ToLibBLSPublicKey(committerKey)
if err != nil {
return nil, ctxerror.New("cannot convert BLS public key",
"blsPublicKey", member.BlsPublicKey,
"coinbaseAddr", header.Coinbase()).WithCause(err)
}
return committerKey, nil
} }
return committerKey, nil
} }
} }
return nil, ctxerror.New("cannot find corresponding BLS Public Key", "coinbaseAddr", header.Coinbase()) return nil, ctxerror.New("cannot find corresponding BLS Public Key", "coinbaseAddr", header.Coinbase())
@ -453,25 +467,94 @@ func (consensus *Consensus) getLeaderPubKeyFromCoinbase(header *block.Header) (*
// (b) node in committed but has any err during processing: Syncing mode // (b) node in committed but has any err during processing: Syncing mode
// (c) node in committed and everything looks good: Normal mode // (c) node in committed and everything looks good: Normal mode
func (consensus *Consensus) UpdateConsensusInformation() Mode { func (consensus *Consensus) UpdateConsensusInformation() Mode {
curHeader := consensus.ChainReader.CurrentHeader()
curEpoch := curHeader.Epoch()
nextEpoch := new(big.Int).Add(curHeader.Epoch(), common.Big1)
if (consensus.ChainReader.Config().IsStaking(nextEpoch) && len(curHeader.ShardState()) > 0 && !consensus.ChainReader.Config().IsStaking(curEpoch)) ||
(consensus.ChainReader.Config().IsStaking(curEpoch) && consensus.Decider.Policy() != quorum.SuperMajorityStake) {
prevSubCommitteeDump := consensus.Decider.JSON()
consensus.Decider = quorum.NewDecider(quorum.SuperMajorityStake)
consensus.Decider.SetShardIDProvider(func() (uint32, error) {
return consensus.ShardID, nil
})
s, err := committee.WithStakingEnabled.ReadFromDB(
nextEpoch, consensus.ChainReader,
)
if err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error when reading staking committee")
return Syncing
}
if _, err := consensus.Decider.SetVoters(
s.FindCommitteeByID(consensus.ShardID).Slots,
); err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error when updating voting power")
return Syncing
}
utils.Logger().Info().
Uint64("block-number", curHeader.Number().Uint64()).
Uint64("curEpoch", curHeader.Epoch().Uint64()).
Uint32("shard-id", consensus.ShardID).
RawJSON("prev-subcommittee", []byte(prevSubCommitteeDump)).
RawJSON("current-subcommittee", []byte(consensus.Decider.JSON())).
Msg("changing committee")
}
pubKeys := []*bls.PublicKey{} pubKeys := []*bls.PublicKey{}
hasError := false hasError := false
header := consensus.ChainReader.CurrentHeader()
epoch := header.Epoch() // TODO: change GetCommitteePublicKeys to read from DB
curPubKeys := committee.WithStakingEnabled.ComputePublicKeys( curShardState, err := committee.WithStakingEnabled.ReadFromDB(
epoch, consensus.ChainReader, curEpoch, consensus.ChainReader,
)[int(header.ShardID())] )
if err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error retrieving current shard state")
return Syncing
}
curCommittee := curShardState.FindCommitteeByID(curHeader.ShardID())
curPubKeys := committee.WithStakingEnabled.GetCommitteePublicKeys(
curCommittee,
)
consensus.numPrevPubKeys = len(curPubKeys) consensus.numPrevPubKeys = len(curPubKeys)
consensus.getLogger().Info().Msg("[UpdateConsensusInformation] Updating.....") consensus.getLogger().Info().Msg("[UpdateConsensusInformation] Updating.....")
if shard.Schedule.IsLastBlock(header.Number().Uint64()) { if len(curHeader.ShardState()) > 0 {
// increase epoch by one if it's the last block // increase curEpoch by one if it's the last block
consensus.SetEpochNum(epoch.Uint64() + 1) consensus.SetEpochNum(curEpoch.Uint64() + 1)
consensus.getLogger().Info().Uint64("headerNum", header.Number().Uint64()). consensus.getLogger().Info().Uint64("headerNum", curHeader.Number().Uint64()).
Msg("[UpdateConsensusInformation] Epoch updated for next epoch") Msg("[UpdateConsensusInformation] Epoch updated for nextEpoch curEpoch")
pubKeys = committee.WithStakingEnabled.ComputePublicKeys(
new(big.Int).Add(epoch, common.Big1), consensus.ChainReader, nextShardState, err := committee.WithStakingEnabled.ReadFromDB(
)[int(header.ShardID())] nextEpoch, consensus.ChainReader,
)
if err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error retrieving nextEpoch shard state")
return Syncing
}
nextCommittee := nextShardState.FindCommitteeByID(curHeader.ShardID())
pubKeys = committee.WithStakingEnabled.GetCommitteePublicKeys(
nextCommittee,
)
} else { } else {
consensus.SetEpochNum(epoch.Uint64()) consensus.SetEpochNum(curEpoch.Uint64())
pubKeys = curPubKeys pubKeys = curPubKeys
} }
@ -488,10 +571,10 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
Msg("[UpdateConsensusInformation] Successfully updated public keys") Msg("[UpdateConsensusInformation] Successfully updated public keys")
consensus.UpdatePublicKeys(pubKeys) consensus.UpdatePublicKeys(pubKeys)
// take care of possible leader change during the epoch // take care of possible leader change during the curEpoch
if !shard.Schedule.IsLastBlock(header.Number().Uint64()) && if !shard.Schedule.IsLastBlock(curHeader.Number().Uint64()) &&
header.Number().Uint64() != 0 { curHeader.Number().Uint64() != 0 {
leaderPubKey, err := consensus.getLeaderPubKeyFromCoinbase(header) leaderPubKey, err := consensus.getLeaderPubKeyFromCoinbase(curHeader)
if err != nil || leaderPubKey == nil { if err != nil || leaderPubKey == nil {
consensus.getLogger().Debug().Err(err). consensus.getLogger().Debug().Err(err).
Msg("[SYNC] Unable to get leaderPubKey from coinbase") Msg("[SYNC] Unable to get leaderPubKey from coinbase")

@ -830,6 +830,7 @@ func (consensus *Consensus) finalizeCommits() {
utils.Logger().Info(). utils.Logger().Info().
Uint64("blockNum", block.NumberU64()). Uint64("blockNum", block.NumberU64()).
Uint64("epochNum", block.Epoch().Uint64()).
Uint64("ViewId", block.Header().ViewID().Uint64()). Uint64("ViewId", block.Header().ViewID().Uint64()).
Str("blockHash", block.Hash().String()). Str("blockHash", block.Hash().String()).
Int("index", consensus.Decider.IndexOf(consensus.PubKey)). Int("index", consensus.Decider.IndexOf(consensus.PubKey)).

@ -148,10 +148,10 @@ func (v *stakedVoteWeight) SetVoters(
v.stakedTotal = numeric.ZeroDec() v.stakedTotal = numeric.ZeroDec()
for i := range staked { for i := range staked {
if staked[i].StakeWithDelegationApplied == nil { if staked[i].TotalStake == nil {
v.hmySlotCount++ v.hmySlotCount++
} else { } else {
v.stakedTotal = v.stakedTotal.Add(*staked[i].StakeWithDelegationApplied) v.stakedTotal = v.stakedTotal.Add(*staked[i].TotalStake)
} }
} }
@ -169,9 +169,9 @@ func (v *stakedVoteWeight) SetVoters(
} }
// Real Staker // Real Staker
if staked[i].StakeWithDelegationApplied != nil { if staked[i].TotalStake != nil {
member.isHarmonyNode = false member.isHarmonyNode = false
member.effectivePercent = staked[i].StakeWithDelegationApplied. member.effectivePercent = staked[i].TotalStake.
Quo(v.stakedTotal). Quo(v.stakedTotal).
Mul(stakersShare) Mul(stakersShare)
theirPercentage = theirPercentage.Add(member.effectivePercent) theirPercentage = theirPercentage.Add(member.effectivePercent)

@ -28,6 +28,7 @@ import (
"time" "time"
"github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/crypto/bls"
lru "github.com/hashicorp/golang-lru"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
@ -48,9 +49,7 @@ import (
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/shard/committee"
staking "github.com/harmony-one/harmony/staking/types" staking "github.com/harmony-one/harmony/staking/types"
lru "github.com/hashicorp/golang-lru"
) )
var ( var (
@ -1156,7 +1155,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
shard := (*shardState)[i] shard := (*shardState)[i]
for j := range shard.Slots { for j := range shard.Slots {
slot := shard.Slots[j] slot := shard.Slots[j]
if slot.StakeWithDelegationApplied != nil { // For external validator if slot.TotalStake != nil { // For external validator
_, ok := processed[slot.EcdsaAddress] _, ok := processed[slot.EcdsaAddress]
if !ok { if !ok {
processed[slot.EcdsaAddress] = struct{}{} processed[slot.EcdsaAddress] = struct{}{}
@ -1961,36 +1960,6 @@ func (bc *BlockChain) GetVrfByNumber(number uint64) []byte {
return header.Vrf() return header.Vrf()
} }
// GetShardState returns the shard state for the given epoch,
// creating one if needed.
func (bc *BlockChain) GetShardState(epoch *big.Int) (shard.State, error) {
shardState, err := bc.ReadShardState(epoch)
if err == nil { // TODO ek – distinguish ErrNotFound
return shardState, err
}
if epoch.Cmp(big.NewInt(GenesisEpoch)) == 0 {
shardState, err = committee.WithStakingEnabled.Compute(
big.NewInt(GenesisEpoch), bc.Config(), nil,
)
} else {
prevEpoch := new(big.Int).Sub(epoch, common.Big1)
shardState, err = committee.WithStakingEnabled.ReadFromDB(
prevEpoch, bc,
)
}
if err != nil {
return nil, err
}
err = bc.WriteShardState(epoch, shardState)
if err != nil {
return nil, err
}
utils.Logger().Debug().Str("epoch", epoch.String()).Msg("saved new shard state")
return shardState, nil
}
// ChainDb returns the database // ChainDb returns the database
func (bc *BlockChain) ChainDb() ethdb.Database { return bc.db } func (bc *BlockChain) ChainDb() ethdb.Database { return bc.db }

@ -243,6 +243,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
} }
} }
st.refundGas() st.refundGas()
// TODO: need to move the gas fee to the general block rewards
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)) st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
return ret, st.gasUsed(), vmerr != nil, err return ret, st.gasUsed(), vmerr != nil, err

@ -225,7 +225,7 @@ func QuorumForBlock(
) (quorum int, err error) { ) (quorum int, err error) {
var ss shard.State var ss shard.State
if reCalculate { if reCalculate {
ss, _ = committee.WithStakingEnabled.Compute(h.Epoch(), chain.Config(), chain) ss, _ = committee.WithStakingEnabled.Compute(h.Epoch(), chain)
} else { } else {
ss, err = chain.ReadShardState(h.Epoch()) ss, err = chain.ReadShardState(h.Epoch())
if err != nil { if err != nil {
@ -284,7 +284,7 @@ func GetPublicKeys(chain engine.ChainReader, header *block.Header, reCalculate b
var shardState shard.State var shardState shard.State
var err error var err error
if reCalculate { if reCalculate {
shardState, _ = committee.WithStakingEnabled.Compute(header.Epoch(), chain.Config(), chain) shardState, _ = committee.WithStakingEnabled.Compute(header.Epoch(), chain)
} else { } else {
shardState, err = chain.ReadShardState(header.Epoch()) shardState, err = chain.ReadShardState(header.Epoch())
if err != nil { if err != nil {

@ -23,33 +23,36 @@ var EpochTBD = big.NewInt(10000000)
var ( var (
// MainnetChainConfig is the chain parameters to run a node on the main network. // MainnetChainConfig is the chain parameters to run a node on the main network.
MainnetChainConfig = &ChainConfig{ MainnetChainConfig = &ChainConfig{
ChainID: MainnetChainID, ChainID: MainnetChainID,
CrossTxEpoch: big.NewInt(28), CrossTxEpoch: big.NewInt(28),
CrossLinkEpoch: EpochTBD, CrossLinkEpoch: EpochTBD,
StakingEpoch: EpochTBD, StakingEpoch: EpochTBD,
EIP155Epoch: big.NewInt(28), PreStakingEpoch: EpochTBD,
S3Epoch: big.NewInt(28), EIP155Epoch: big.NewInt(28),
S3Epoch: big.NewInt(28),
} }
// TestnetChainConfig contains the chain parameters to run a node on the harmony test network. // TestnetChainConfig contains the chain parameters to run a node on the harmony test network.
TestnetChainConfig = &ChainConfig{ TestnetChainConfig = &ChainConfig{
ChainID: TestnetChainID, ChainID: TestnetChainID,
CrossTxEpoch: big.NewInt(0), CrossTxEpoch: big.NewInt(0),
CrossLinkEpoch: big.NewInt(0), CrossLinkEpoch: big.NewInt(2),
StakingEpoch: big.NewInt(3), StakingEpoch: big.NewInt(3),
EIP155Epoch: big.NewInt(0), PreStakingEpoch: big.NewInt(0),
S3Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0),
} }
// PangaeaChainConfig contains the chain parameters for the Pangaea network. // PangaeaChainConfig contains the chain parameters for the Pangaea network.
// All features except for CrossLink are enabled at launch. // All features except for CrossLink are enabled at launch.
PangaeaChainConfig = &ChainConfig{ PangaeaChainConfig = &ChainConfig{
ChainID: PangaeaChainID, ChainID: PangaeaChainID,
CrossTxEpoch: big.NewInt(0), CrossTxEpoch: big.NewInt(0),
CrossLinkEpoch: EpochTBD, CrossLinkEpoch: EpochTBD,
StakingEpoch: EpochTBD, StakingEpoch: EpochTBD,
EIP155Epoch: big.NewInt(0), PreStakingEpoch: EpochTBD,
S3Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0),
} }
// AllProtocolChanges ... // AllProtocolChanges ...
@ -60,6 +63,7 @@ var (
big.NewInt(0), // CrossTxEpoch big.NewInt(0), // CrossTxEpoch
big.NewInt(0), // CrossLinkEpoch big.NewInt(0), // CrossLinkEpoch
big.NewInt(0), // StakingEpoch big.NewInt(0), // StakingEpoch
big.NewInt(0), // PreStakingEpoch
big.NewInt(0), // EIP155Epoch big.NewInt(0), // EIP155Epoch
big.NewInt(0), // S3Epoch big.NewInt(0), // S3Epoch
} }
@ -72,6 +76,7 @@ var (
big.NewInt(0), // CrossTxEpoch big.NewInt(0), // CrossTxEpoch
big.NewInt(0), // CrossLinkEpoch big.NewInt(0), // CrossLinkEpoch
big.NewInt(0), // StakingEpoch big.NewInt(0), // StakingEpoch
big.NewInt(0), // PreStakingEpoch
big.NewInt(0), // EIP155Epoch big.NewInt(0), // EIP155Epoch
big.NewInt(0), // S3Epoch big.NewInt(0), // S3Epoch
} }
@ -108,9 +113,12 @@ type ChainConfig struct {
// cross-shard links. // cross-shard links.
CrossLinkEpoch *big.Int `json:"crossLinkEpoch,omitempty"` CrossLinkEpoch *big.Int `json:"crossLinkEpoch,omitempty"`
// StakingEpoch is the epoch we allow staking transactions // StakingEpoch is the epoch when shard assign takes staking into account
StakingEpoch *big.Int `json:"stakingEpoch,omitempty"` StakingEpoch *big.Int `json:"stakingEpoch,omitempty"`
// PreStakingEpoch is the epoch we allow staking transactions
PreStakingEpoch *big.Int `json:"preStakingEpoch,omitempty"`
EIP155Epoch *big.Int `json:"eip155Epoch,omitempty"` // EIP155 hard fork epoch (include EIP158 too) EIP155Epoch *big.Int `json:"eip155Epoch,omitempty"` // EIP155 hard fork epoch (include EIP158 too)
S3Epoch *big.Int `json:"s3Epoch,omitempty"` // S3 epoch is the first epoch containing S3 mainnet and all ethereum update up to Constantinople S3Epoch *big.Int `json:"s3Epoch,omitempty"` // S3 epoch is the first epoch containing S3 mainnet and all ethereum update up to Constantinople
} }
@ -151,6 +159,11 @@ func (c *ChainConfig) IsStaking(epoch *big.Int) bool {
return isForked(c.StakingEpoch, epoch) return isForked(c.StakingEpoch, epoch)
} }
// IsPreStaking determines whether staking transactions are allowed
func (c *ChainConfig) IsPreStaking(epoch *big.Int) bool {
return isForked(c.PreStakingEpoch, epoch)
}
// IsCrossLink returns whether epoch is either equal to the CrossLink fork epoch or greater. // IsCrossLink returns whether epoch is either equal to the CrossLink fork epoch or greater.
func (c *ChainConfig) IsCrossLink(epoch *big.Int) bool { func (c *ChainConfig) IsCrossLink(epoch *big.Int) bool {
return isForked(c.CrossLinkEpoch, epoch) return isForked(c.CrossLinkEpoch, epoch)

@ -86,6 +86,18 @@ func GetAddressFromBlsPubKey(pubKey *bls.PublicKey) common.Address {
return addr return addr
} }
// GetAddressFromBlsPubKeyBytes return the address object from bls pub key.
func GetAddressFromBlsPubKeyBytes(pubKeyBytes []byte) common.Address {
pubKey := &bls.PublicKey{}
err := pubKey.Deserialize(pubKeyBytes[:])
addr := common.Address{}
if err != nil {
addrBytes := pubKey.GetAddress()
addr.SetBytes(addrBytes[:])
}
return addr
}
// GenKeyP2P generates a pair of RSA keys used in libp2p host // GenKeyP2P generates a pair of RSA keys used in libp2p host
func GenKeyP2P(ip, port string) (p2p_crypto.PrivKey, p2p_crypto.PubKey, error) { func GenKeyP2P(ip, port string) (p2p_crypto.PrivKey, p2p_crypto.PubKey, error) {
r := mrand.New(mrand.NewSource(int64(GetUniqueIDFromIPPort(ip, port)))) r := mrand.New(mrand.NewSource(int64(GetUniqueIDFromIPPort(ip, port))))

@ -278,17 +278,20 @@ func (node *Node) addPendingTransactions(newTxs types.Transactions) {
// Add new staking transactions to the pending staking transaction list. // Add new staking transactions to the pending staking transaction list.
func (node *Node) addPendingStakingTransactions(newStakingTxs staking.StakingTransactions) { func (node *Node) addPendingStakingTransactions(newStakingTxs staking.StakingTransactions) {
txPoolLimit := 1000 // TODO: incorporate staking txn into TxPool txPoolLimit := 1000 // TODO: incorporate staking txn into TxPool
node.pendingStakingTxMutex.Lock()
for _, tx := range newStakingTxs { if node.Blockchain().Config().IsPreStaking(node.Worker.GetNewEpoch()) {
if _, ok := node.pendingStakingTransactions[tx.Hash()]; !ok { node.pendingStakingTxMutex.Lock()
node.pendingStakingTransactions[tx.Hash()] = tx for _, tx := range newStakingTxs {
} if _, ok := node.pendingStakingTransactions[tx.Hash()]; !ok {
if len(node.pendingStakingTransactions) > txPoolLimit { node.pendingStakingTransactions[tx.Hash()] = tx
break }
if len(node.pendingStakingTransactions) > txPoolLimit {
break
}
} }
utils.Logger().Info().Int("length of newStakingTxs", len(newStakingTxs)).Int("totalPending", len(node.pendingStakingTransactions)).Msg("Got more staking transactions")
node.pendingStakingTxMutex.Unlock()
} }
utils.Logger().Info().Int("length of newStakingTxs", len(newStakingTxs)).Int("totalPending", len(node.pendingStakingTransactions)).Msg("Got more staking transactions")
node.pendingStakingTxMutex.Unlock()
} }
// AddPendingStakingTransaction staking transactions // AddPendingStakingTransaction staking transactions
@ -486,9 +489,12 @@ func (node *Node) InitConsensusWithValidators() (err error) {
Uint32("shardID", shardID). Uint32("shardID", shardID).
Uint64("epoch", epoch.Uint64()). Uint64("epoch", epoch.Uint64()).
Msg("[InitConsensusWithValidators] Try To Get PublicKeys") Msg("[InitConsensusWithValidators] Try To Get PublicKeys")
pubKeys := committee.WithStakingEnabled.ComputePublicKeys( shardState, err := committee.WithStakingEnabled.Compute(
epoch, node.Consensus.ChainReader, epoch, node.Consensus.ChainReader,
)[int(shardID)] )
pubKeys := committee.WithStakingEnabled.GetCommitteePublicKeys(
shardState.FindCommitteeByID(shardID),
)
if len(pubKeys) == 0 { if len(pubKeys) == 0 {
utils.Logger().Error(). utils.Logger().Error().
Uint32("shardID", shardID). Uint32("shardID", shardID).

@ -41,7 +41,7 @@ type genesisInitializer struct {
// InitChainDB sets up a new genesis block in the database for the given shard. // InitChainDB sets up a new genesis block in the database for the given shard.
func (gi *genesisInitializer) InitChainDB(db ethdb.Database, shardID uint32) error { func (gi *genesisInitializer) InitChainDB(db ethdb.Database, shardID uint32) error {
shardState, _ := committee.WithStakingEnabled.Compute( shardState, _ := committee.WithStakingEnabled.Compute(
big.NewInt(core.GenesisEpoch), &gi.node.chainConfig, nil, big.NewInt(core.GenesisEpoch), nil,
) )
if shardID != shard.BeaconChainShardID { if shardID != shard.BeaconChainShardID {
// store only the local shard for shard chains // store only the local shard for shard chains

@ -8,7 +8,6 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
@ -16,7 +15,6 @@ import (
proto_discovery "github.com/harmony-one/harmony/api/proto/discovery" proto_discovery "github.com/harmony-one/harmony/api/proto/discovery"
proto_node "github.com/harmony-one/harmony/api/proto/node" proto_node "github.com/harmony-one/harmony/api/proto/node"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
bls2 "github.com/harmony-one/harmony/crypto/bls" bls2 "github.com/harmony-one/harmony/crypto/bls"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
@ -26,7 +24,6 @@ import (
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/shard/committee"
staking "github.com/harmony-one/harmony/staking/types" staking "github.com/harmony-one/harmony/staking/types"
libp2p_peer "github.com/libp2p/go-libp2p-core/peer" libp2p_peer "github.com/libp2p/go-libp2p-core/peer"
) )
@ -345,7 +342,12 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block, commitSigAndBit
node.BroadcastCXReceipts(newBlock, commitSigAndBitmap) node.BroadcastCXReceipts(newBlock, commitSigAndBitmap)
} else { } else {
utils.Logger().Info(). utils.Logger().Info().
Uint64("BlockNum", newBlock.NumberU64()). Uint64("blockNum", newBlock.NumberU64()).
Uint64("epochNum", newBlock.Epoch().Uint64()).
Uint64("ViewId", newBlock.Header().ViewID().Uint64()).
Str("blockHash", newBlock.Hash().String()).
Int("numTxns", len(newBlock.Transactions())).
Int("numStakingTxns", len(newBlock.StakingTransactions())).
Msg("BINGO !!! Reached Consensus") Msg("BINGO !!! Reached Consensus")
// 15% of the validator also need to do broadcasting // 15% of the validator also need to do broadcasting
rand.Seed(time.Now().UTC().UnixNano()) rand.Seed(time.Now().UTC().UnixNano())
@ -377,51 +379,7 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block, commitSigAndBit
// Update consensus keys at last so the change of leader status doesn't mess up normal flow // Update consensus keys at last so the change of leader status doesn't mess up normal flow
if len(newBlock.Header().ShardState()) > 0 { if len(newBlock.Header().ShardState()) > 0 {
next := new(big.Int).Add(newBlock.Epoch(), common.Big1)
if node.chainConfig.StakingEpoch.Cmp(next) == 0 &&
node.Consensus.Decider.Policy() != quorum.SuperMajorityStake {
node.Consensus.Decider = quorum.NewDecider(quorum.SuperMajorityStake)
node.Consensus.Decider.SetShardIDProvider(func() (uint32, error) {
return node.Consensus.ShardID, nil
})
s, _ := committee.WithStakingEnabled.Compute(
next, &node.chainConfig, node.Consensus.ChainReader,
)
prevSubCommitteeDump := node.Consensus.Decider.JSON()
if _, err := node.Consensus.Decider.SetVoters(
s.FindCommitteeByID(node.Consensus.ShardID).Slots,
); err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", node.Consensus.ShardID).
Msg("Error when updating voting power")
return
}
utils.Logger().Info().
Uint64("block-number", newBlock.Number().Uint64()).
Uint64("epoch", newBlock.Epoch().Uint64()).
Uint32("shard-id", node.Consensus.ShardID).
RawJSON("prev-subcommittee", []byte(prevSubCommitteeDump)).
RawJSON("current-subcommittee", []byte(node.Consensus.Decider.JSON())).
Msg("changing committee")
}
// TODO Need to refactor UpdateConsensusInformation so can fold the following logic
// into UCI - todo because UCI mutates state & called in overloaded contexts
node.Consensus.UpdateConsensusInformation() node.Consensus.UpdateConsensusInformation()
if shard.Schedule.IsLastBlock(newBlock.Number().Uint64()) {
if node.chainConfig.StakingEpoch.Cmp(next) == 0 {
// Hit this case again, need after UpdateConsensus
curPubKeys := committee.WithStakingEnabled.ComputePublicKeys(
next, node.Consensus.ChainReader,
)[int(node.Consensus.ShardID)]
node.Consensus.Decider.UpdateParticipants(curPubKeys)
}
}
} }
// TODO chao: uncomment this after beacon syncing is stable // TODO chao: uncomment this after beacon syncing is stable

@ -79,6 +79,16 @@ func (node *Node) proposeNewBlock() (*types.Block, error) {
// Update worker's current header and state data in preparation to propose/process new transactions // Update worker's current header and state data in preparation to propose/process new transactions
coinbase := node.Consensus.SelfAddress coinbase := node.Consensus.SelfAddress
// After staking, all coinbase will be the address of bls pub key
if node.Blockchain().Config().IsStaking(node.Worker.GetNewEpoch()) {
addr := common.Address{}
blsPubKeyBytes := node.Consensus.PubKey.GetAddress()
addr.SetBytes(blsPubKeyBytes[:])
coinbase = addr
}
node.Worker.UpdateCurrent()
// Prepare transactions including staking transactions // Prepare transactions including staking transactions
pending, err := node.TxPool.Pending() pending, err := node.TxPool.Pending()
if err != nil { if err != nil {
@ -88,14 +98,16 @@ func (node *Node) proposeNewBlock() (*types.Block, error) {
// TODO: integrate staking transaction into tx pool // TODO: integrate staking transaction into tx pool
pendingStakingTransactions := types2.StakingTransactions{} pendingStakingTransactions := types2.StakingTransactions{}
node.pendingStakingTxMutex.Lock() // Only process staking transactions after pre-staking epoch happened.
for _, tx := range node.pendingStakingTransactions { if node.Blockchain().Config().IsPreStaking(node.Worker.GetNewEpoch()) {
pendingStakingTransactions = append(pendingStakingTransactions, tx) node.pendingStakingTxMutex.Lock()
for _, tx := range node.pendingStakingTransactions {
pendingStakingTransactions = append(pendingStakingTransactions, tx)
}
node.pendingStakingTransactions = make(map[common.Hash]*types2.StakingTransaction)
node.pendingStakingTxMutex.Unlock()
} }
node.pendingStakingTransactions = make(map[common.Hash]*types2.StakingTransaction)
node.pendingStakingTxMutex.Unlock()
node.Worker.UpdateCurrent(coinbase)
if err := node.Worker.CommitTransactions(pending, pendingStakingTransactions, coinbase); err != nil { if err := node.Worker.CommitTransactions(pending, pendingStakingTransactions, coinbase); err != nil {
utils.Logger().Error().Err(err).Msg("cannot commit transactions") utils.Logger().Error().Err(err).Msg("cannot commit transactions")
return nil, err return nil, err
@ -119,8 +131,9 @@ func (node *Node) proposeNewBlock() (*types.Block, error) {
} }
// Prepare shard state // Prepare shard state
// NOTE: this will potentially override shard chain's epoch to beacon chain's epoch during staking migration period.
shardState, err := node.Worker.SuperCommitteeForNextEpoch( shardState, err := node.Worker.SuperCommitteeForNextEpoch(
node.Consensus.ShardID, node.Blockchain(), node.Consensus.ShardID, node.Beaconchain(),
) )
if err != nil { if err != nil {

@ -215,7 +215,7 @@ func (w *Worker) CommitReceipts(receiptsList []*types.CXReceiptsProof) error {
} }
// UpdateCurrent updates the current environment with the current state and header. // UpdateCurrent updates the current environment with the current state and header.
func (w *Worker) UpdateCurrent(coinbase common.Address) error { func (w *Worker) UpdateCurrent() error {
parent := w.chain.CurrentBlock() parent := w.chain.CurrentBlock()
num := parent.Number() num := parent.Number()
timestamp := time.Now().Unix() timestamp := time.Now().Unix()
@ -227,7 +227,6 @@ func (w *Worker) UpdateCurrent(coinbase common.Address) error {
GasLimit(core.CalcGasLimit(parent, w.gasFloor, w.gasCeil)). GasLimit(core.CalcGasLimit(parent, w.gasFloor, w.gasCeil)).
Time(big.NewInt(timestamp)). Time(big.NewInt(timestamp)).
ShardID(w.chain.ShardID()). ShardID(w.chain.ShardID()).
Coinbase(coinbase).
Header() Header()
return w.makeCurrent(parent, header) return w.makeCurrent(parent, header)
} }
@ -288,39 +287,73 @@ func (w *Worker) SuperCommitteeForNextEpoch(
) (shard.State, error) { ) (shard.State, error) {
var ( var (
nextCommittee shard.State nextCommittee shard.State
oops error err error
) )
switch shardID { switch shardID {
case shard.BeaconChainShardID: case shard.BeaconChainShardID:
if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) { if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) {
nextCommittee, oops = committee.WithStakingEnabled.Compute( nextCommittee, err = committee.WithStakingEnabled.Compute(
new(big.Int).Add(w.current.header.Epoch(), common.Big1), new(big.Int).Add(w.current.header.Epoch(), common.Big1),
w.config,
beacon, beacon,
) )
} }
default: default:
// WARN When we first enable staking, this condition may not be robust by itself. // TODO: needs to make sure beacon chain sync works.
beaconEpoch := beacon.CurrentHeader().Epoch()
if w.config.IsStaking(w.current.header.Epoch()) { nextEpoch := new(big.Int).Add(w.current.header.Epoch(), common.Big1)
switch beacon.CurrentHeader().Epoch().Cmp(w.current.header.Epoch()) { if w.config.IsStaking(nextEpoch) {
// If next epoch is staking epoch, I should wait and listen for beacon chain for epoch changes
switch beaconEpoch.Cmp(w.current.header.Epoch()) {
case 1: case 1:
nextCommittee, oops = committee.WithStakingEnabled.ReadFromDB( // If beacon chain is bigger than shard chain in epoch, it means I should catch up with beacon chain now
beacon.CurrentHeader().Epoch(), beacon, nextCommittee, err = committee.WithStakingEnabled.ReadFromDB(
beaconEpoch, beacon,
) )
// Set this block's epoch to be beaconEpoch - 1, so the next block will have beaconEpoch
// This shouldn't be exactly beaconEpoch because the next block will have beaconEpoch + 1
blockEpoch := big.NewInt(0).Set(beaconEpoch).Sub(beaconEpoch, big.NewInt(1))
utils.Logger().Debug().
Uint64("blockNum", w.current.header.Number().Uint64()).
Uint64("myPrevEpoch", w.current.header.Epoch().Uint64()).
Uint64("myCurEpoch", blockEpoch.Uint64()).
Msg("Propose new epoch as beacon chain's epoch")
w.current.header.SetEpoch(blockEpoch)
case 0:
// If it's same epoch, no need to propose new shard state (new epoch change)
case -1:
// If beacon chain is behind, shard chain should wait for the beacon chain by not changing epochs.
} }
} else { } else {
if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) { if w.config.IsStaking(beaconEpoch) {
nextCommittee, oops = committee.WithStakingEnabled.Compute( // If I am not even in the last epoch before staking epoch and beacon chain is already in staking epoch,
new(big.Int).Add(w.current.header.Epoch(), common.Big1), // I should just catch up with beacon chain's epoch
w.config, nextCommittee, err = committee.WithStakingEnabled.ReadFromDB(
beacon, beaconEpoch, beacon,
) )
blockEpoch := big.NewInt(0).Set(beaconEpoch).Sub(beaconEpoch, big.NewInt(1))
utils.Logger().Debug().
Uint64("blockNum", w.current.header.Number().Uint64()).
Uint64("myPrevEpoch", w.current.header.Epoch().Uint64()).
Uint64("myCurEpoch", blockEpoch.Uint64()).
Msg("Propose one-time catch up with beacon chain's epoch")
// Set this block's epoch to be beaconEpoch - 1, so the next block will have beaconEpoch
w.current.header.SetEpoch(blockEpoch)
} else {
// If I are not in staking nor has beacon chain proposed a staking-based shard state,
// do pre-staking committee calculation
if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) {
nextCommittee, err = committee.WithStakingEnabled.Compute(
new(big.Int).Add(w.current.header.Epoch(), common.Big1),
w.chain,
)
}
} }
} }
} }
return nextCommittee, oops return nextCommittee, err
} }
// FinalizeNewBlock generate a new block for the next consensus round. // FinalizeNewBlock generate a new block for the next consensus round.
@ -364,6 +397,7 @@ func (w *Worker) FinalizeNewBlock(sig []byte, signers []byte, viewID uint64, coi
s := w.current.state.Copy() s := w.current.state.Copy()
copyHeader := types.CopyHeader(w.current.header) copyHeader := types.CopyHeader(w.current.header)
// TODO: feed coinbase into here so the proposer gets extra rewards.
block, err := w.engine.Finalize(w.chain, copyHeader, s, w.current.txs, w.current.receipts, w.current.outcxs, w.current.incxs, w.current.stakingTxs) block, err := w.engine.Finalize(w.chain, copyHeader, s, w.current.txs, w.current.receipts, w.current.outcxs, w.current.incxs, w.current.stakingTxs)
if err != nil { if err != nil {
return nil, ctxerror.New("cannot finalize block").WithCause(err) return nil, ctxerror.New("cannot finalize block").WithCause(err)

@ -8,7 +8,6 @@ import (
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
common2 "github.com/harmony-one/harmony/internal/common" common2 "github.com/harmony-one/harmony/internal/common"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding" shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
@ -19,22 +18,14 @@ import (
// ValidatorListProvider .. // ValidatorListProvider ..
type ValidatorListProvider interface { type ValidatorListProvider interface {
Compute( Compute(
epoch *big.Int, config *params.ChainConfig, reader DataProvider, epoch *big.Int, reader DataProvider,
) (shard.State, error) ) (shard.State, error)
ReadFromDB(epoch *big.Int, reader DataProvider) (shard.State, error) ReadFromDB(epoch *big.Int, reader DataProvider) (shard.State, error)
} GetCommitteePublicKeys(committee *shard.Committee) []*bls.PublicKey
// PublicKeysProvider per epoch
type PublicKeysProvider interface {
ComputePublicKeys(epoch *big.Int, reader DataProvider) [][]*bls.PublicKey
ReadPublicKeysFromDB(
hash common.Hash, reader DataProvider,
) ([]*bls.PublicKey, error)
} }
// Reader is committee.Reader and it is the API that committee membership assignment needs // Reader is committee.Reader and it is the API that committee membership assignment needs
type Reader interface { type Reader interface {
PublicKeysProvider
ValidatorListProvider ValidatorListProvider
} }
@ -123,7 +114,6 @@ func eposStakedCommittee(
// TODO benchmark difference if went with data structure that sorts on insert // TODO benchmark difference if went with data structure that sorts on insert
for i := range candidates { for i := range candidates {
// TODO Should be using .ValidatorStakingWithDelegation, not implemented yet
validator, err := stakerReader.ReadValidatorData(candidates[i]) validator, err := stakerReader.ReadValidatorData(candidates[i])
validatorStake := big.NewInt(0) validatorStake := big.NewInt(0)
for _, delegation := range validator.Delegations { for _, delegation := range validator.Delegations {
@ -184,59 +174,19 @@ func eposStakedCommittee(
return superComm, nil return superComm, nil
} }
// ComputePublicKeys produces publicKeys of entire supercommittee per epoch // GetCommitteePublicKeys returns the public keys of a shard
func (def partialStakingEnabled) ComputePublicKeys( func (def partialStakingEnabled) GetCommitteePublicKeys(committee *shard.Committee) []*bls.PublicKey {
epoch *big.Int, d DataProvider, allIdentities := make([]*bls.PublicKey, len(committee.Slots))
) [][]*bls.PublicKey {
config := d.Config()
superComm, _ := def.Compute(epoch, config, d)
allIdentities := make([][]*bls.PublicKey, len(superComm)) for i := range committee.Slots {
identity := &bls.PublicKey{}
for i := range superComm { committee.Slots[i].BlsPublicKey.ToLibBLSPublicKey(identity)
allIdentities[i] = make([]*bls.PublicKey, len(superComm[i].Slots)) allIdentities[i] = identity
for j := range superComm[i].Slots {
identity := &bls.PublicKey{}
superComm[i].Slots[j].BlsPublicKey.ToLibBLSPublicKey(identity)
allIdentities[i][j] = identity
}
} }
return allIdentities return allIdentities
} }
func (def partialStakingEnabled) ReadPublicKeysFromDB(
h common.Hash, reader DataProvider,
) ([]*bls.PublicKey, error) {
header := reader.GetHeaderByHash(h)
shardID := header.ShardID()
superCommittee, err := reader.ReadShardState(header.Epoch())
if err != nil {
return nil, err
}
subCommittee := superCommittee.FindCommitteeByID(shardID)
if subCommittee == nil {
return nil, ctxerror.New("cannot find shard in the shard state",
"blockNumber", header.Number(),
"shardID", header.ShardID(),
)
}
committerKeys := []*bls.PublicKey{}
for i := range subCommittee.Slots {
committerKey := new(bls.PublicKey)
err := subCommittee.Slots[i].BlsPublicKey.ToLibBLSPublicKey(committerKey)
if err != nil {
return nil, ctxerror.New("cannot convert BLS public key",
"blsPublicKey", subCommittee.Slots[i].BlsPublicKey).WithCause(err)
}
committerKeys = append(committerKeys, committerKey)
}
return committerKeys, nil
return nil, nil
}
func (def partialStakingEnabled) ReadFromDB( func (def partialStakingEnabled) ReadFromDB(
epoch *big.Int, reader DataProvider, epoch *big.Int, reader DataProvider,
) (newSuperComm shard.State, err error) { ) (newSuperComm shard.State, err error) {
@ -245,10 +195,18 @@ func (def partialStakingEnabled) ReadFromDB(
// ReadFromComputation is single entry point for reading the State of the network // ReadFromComputation is single entry point for reading the State of the network
func (def partialStakingEnabled) Compute( func (def partialStakingEnabled) Compute(
epoch *big.Int, config *params.ChainConfig, stakerReader DataProvider, epoch *big.Int, stakerReader DataProvider,
) (newSuperComm shard.State, err error) { ) (newSuperComm shard.State, err error) {
preStaking := true
if stakerReader != nil {
config := stakerReader.Config()
if config.IsStaking(epoch) {
preStaking = false
}
}
instance := shard.Schedule.InstanceForEpoch(epoch) instance := shard.Schedule.InstanceForEpoch(epoch)
if !config.IsStaking(epoch) { if preStaking {
return preStakingEnabledCommittee(instance), nil return preStakingEnabledCommittee(instance), nil
} }
stakedSlots := stakedSlots :=

@ -39,7 +39,7 @@ type Slot struct {
EcdsaAddress common.Address `json:"ecdsa-address"` EcdsaAddress common.Address `json:"ecdsa-address"`
BlsPublicKey BlsPublicKey `json:"bls-pubkey"` BlsPublicKey BlsPublicKey `json:"bls-pubkey"`
// nil means our node, 0 means not active, > 0 means staked node // nil means our node, 0 means not active, > 0 means staked node
StakeWithDelegationApplied *numeric.Dec `json:"staked-validator" rlp:"nil"` TotalStake *numeric.Dec `json:"total-stake" rlp:"nil"`
} }
// SlotList is a list of SlotList. // SlotList is a list of SlotList.
@ -71,7 +71,7 @@ func (ss State) JSON() string {
for j := range ss[i].Slots { for j := range ss[i].Slots {
n := ss[i].Slots[j] n := ss[i].Slots[j]
dump[i].NodeList[j].BlsPublicKey = n.BlsPublicKey dump[i].NodeList[j].BlsPublicKey = n.BlsPublicKey
dump[i].NodeList[j].StakeWithDelegationApplied = n.StakeWithDelegationApplied dump[i].NodeList[j].TotalStake = n.TotalStake
dump[i].NodeList[j].EcdsaAddress = common2.MustAddressToBech32(n.EcdsaAddress) dump[i].NodeList[j].EcdsaAddress = common2.MustAddressToBech32(n.EcdsaAddress)
} }
} }
@ -266,5 +266,9 @@ func (n Slot) Serialize() []byte {
} }
func (n Slot) String() string { func (n Slot) String() string {
return "ECDSA: " + common2.MustAddressToBech32(n.EcdsaAddress) + ", BLS: " + hex.EncodeToString(n.BlsPublicKey[:]) total := "nil"
if n.TotalStake != nil {
total = n.TotalStake.String()
}
return "ECDSA: " + common2.MustAddressToBech32(n.EcdsaAddress) + ", BLS: " + hex.EncodeToString(n.BlsPublicKey[:]) + ", TotalStake: " + total
} }

@ -8,19 +8,18 @@
127.0.0.1 9007 validator one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9 c4e4708b6cf2a2ceeb59981677e9821eebafc5cf483fb5364a28fa604cc0ce69beeed40f3f03815c9e196fdaec5f1097 127.0.0.1 9007 validator one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9 c4e4708b6cf2a2ceeb59981677e9821eebafc5cf483fb5364a28fa604cc0ce69beeed40f3f03815c9e196fdaec5f1097
127.0.0.1 9008 validator one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc 86dc2fdc2ceec18f6923b99fd86a68405c132e1005cf1df72dca75db0adfaeb53d201d66af37916d61f079f34f21fb96 127.0.0.1 9008 validator one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc 86dc2fdc2ceec18f6923b99fd86a68405c132e1005cf1df72dca75db0adfaeb53d201d66af37916d61f079f34f21fb96
127.0.0.1 9009 validator one1658znfwf40epvy7e46cqrmzyy54h4n0qa73nep 49d15743b36334399f9985feb0753430a2b287b2d68b84495bbb15381854cbf01bca9d1d9f4c9c8f18509b2bfa6bd40f 127.0.0.1 9009 validator one1658znfwf40epvy7e46cqrmzyy54h4n0qa73nep 49d15743b36334399f9985feb0753430a2b287b2d68b84495bbb15381854cbf01bca9d1d9f4c9c8f18509b2bfa6bd40f
127.0.0.1 9010 validator one1a50tun737ulcvwy0yvve0pvu5skq0kjargvhwe 52ecce5f64db21cbe374c9268188f5d2cdd5bec1a3112276a350349860e35fb81f8cfe447a311e0550d961cf25cb988d 127.0.0.1 9010 validator one1z05g55zamqzfw9qs432n33gycdmyvs38xjemyl 95117937cd8c09acd2dfae847d74041a67834ea88662a7cbed1e170350bc329e53db151e5a0ef3e712e35287ae954818
127.0.0.1 9011 validator one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100 127.0.0.1 9011 validator one1ljznytjyn269azvszjlcqvpcj6hjm822yrcp2e 68ae289d73332872ec8d04ac256ca0f5453c88ad392730c5741b6055bc3ec3d086ab03637713a29f459177aaa8340615
127.0.0.1 9012 validator one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7 678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c
127.0.0.1 9013 validator one129r9pj3sk0re76f7zs3qz92rggmdgjhtwge62k 63f479f249c59f0486fda8caa2ffb247209489dae009dfde6144ff38c370230963d360dffd318cfb26c213320e89a512
127.0.0.1 9099 explorer
127.0.0.1 9100 validator one1ghkz3frhske7emk79p7v2afmj4a5t0kmjyt4s5 eca09c1808b729ca56f1b5a6a287c6e1c3ae09e29ccf7efa35453471fcab07d9f73cee249e2b91f5ee44eb9618be3904 127.0.0.1 9100 validator one1a50tun737ulcvwy0yvve0pvu5skq0kjargvhwe 52ecce5f64db21cbe374c9268188f5d2cdd5bec1a3112276a350349860e35fb81f8cfe447a311e0550d961cf25cb988d
127.0.0.1 9101 validator one1d7jfnr6yraxnrycgaemyktkmhmajhp8kl0yahv f47238daef97d60deedbde5302d05dea5de67608f11f406576e363661f7dcbc4a1385948549b31a6c70f6fde8a391486 127.0.0.1 9101 validator one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100
127.0.0.1 9102 validator one1r4zyyjqrulf935a479sgqlpa78kz7zlcg2jfen fc4b9c535ee91f015efff3f32fbb9d32cdd9bfc8a837bb3eee89b8fff653c7af2050a4e147ebe5c7233dc2d5df06ee0a 127.0.0.1 9102 validator one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7 678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c
127.0.0.1 9103 validator one1p7ht2d4kl8ve7a8jxw746yfnx4wnfxtp8jqxwe ca86e551ee42adaaa6477322d7db869d3e203c00d7b86c82ebee629ad79cb6d57b8f3db28336778ec2180e56a8e07296 127.0.0.1 9103 validator one129r9pj3sk0re76f7zs3qz92rggmdgjhtwge62k 63f479f249c59f0486fda8caa2ffb247209489dae009dfde6144ff38c370230963d360dffd318cfb26c213320e89a512
127.0.0.1 9104 validator one1z05g55zamqzfw9qs432n33gycdmyvs38xjemyl 95117937cd8c09acd2dfae847d74041a67834ea88662a7cbed1e170350bc329e53db151e5a0ef3e712e35287ae954818 127.0.0.1 9104 validator one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc 16513c487a6bb76f37219f3c2927a4f281f9dd3fd6ed2e3a64e500de6545cf391dd973cc228d24f9bd01efe94912e714
127.0.0.1 9105 validator one1ljznytjyn269azvszjlcqvpcj6hjm822yrcp2e 68ae289d73332872ec8d04ac256ca0f5453c88ad392730c5741b6055bc3ec3d086ab03637713a29f459177aaa8340615 127.0.0.1 9105 validator one1658znfwf40epvy7e46cqrmzyy54h4n0qa73nep 576d3c48294e00d6be4a22b07b66a870ddee03052fe48a5abbd180222e5d5a1f8946a78d55b025de21635fd743bbad90
127.0.0.1 9107 validator one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100 127.0.0.1 9106 validator one1ghkz3frhske7emk79p7v2afmj4a5t0kmjyt4s5 eca09c1808b729ca56f1b5a6a287c6e1c3ae09e29ccf7efa35453471fcab07d9f73cee249e2b91f5ee44eb9618be3904
127.0.0.1 9108 validator one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7 678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c 127.0.0.1 9107 validator one1d7jfnr6yraxnrycgaemyktkmhmajhp8kl0yahv f47238daef97d60deedbde5302d05dea5de67608f11f406576e363661f7dcbc4a1385948549b31a6c70f6fde8a391486
127.0.0.1 9109 validator one1658znfwf40epvy7e46cqrmzyy54h4n0qa73nep 576d3c48294e00d6be4a22b07b66a870ddee03052fe48a5abbd180222e5d5a1f8946a78d55b025de21635fd743bbad90 127.0.0.1 9108 validator one1r4zyyjqrulf935a479sgqlpa78kz7zlcg2jfen fc4b9c535ee91f015efff3f32fbb9d32cdd9bfc8a837bb3eee89b8fff653c7af2050a4e147ebe5c7233dc2d5df06ee0a
127.0.0.1 9110 validator one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc 16513c487a6bb76f37219f3c2927a4f281f9dd3fd6ed2e3a64e500de6545cf391dd973cc228d24f9bd01efe94912e714 127.0.0.1 9109 validator one1p7ht2d4kl8ve7a8jxw746yfnx4wnfxtp8jqxwe ca86e551ee42adaaa6477322d7db869d3e203c00d7b86c82ebee629ad79cb6d57b8f3db28336778ec2180e56a8e07296
127.0.0.1 9099 explorer
Loading…
Cancel
Save