Refactor shard compute logic and make local test friendly for staking

pull/1870/head
Rongjian Lan 5 years ago
parent 7db45a54c7
commit 9070421462
  1. 12
      cmd/staking/root.go
  2. 73
      consensus/consensus_service.go
  3. 12
      consensus/quorum/one-node-staked-vote.go
  4. 5
      core/blockchain.go
  5. 4
      internal/chain/engine.go
  6. 5
      node/node.go
  7. 2
      node/node_genesis.go
  8. 47
      node/node_handler.go
  9. 3
      node/worker/worker.go
  10. 30
      shard/committee/assignment.go
  11. 10
      shard/shard_state.go
  12. 29
      test/configs/local-resharding.txt

@ -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 {

@ -453,12 +453,69 @@ 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()
next := new(big.Int).Add(curHeader.Epoch(), common.Big1)
if consensus.ChainReader.Config().IsStaking(next) &&
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.Compute(
next, consensus.ChainReader,
)
if err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error when computing committee with staking")
return Syncing
}
utils.Logger().Print("XXXXXXXX")
utils.Logger().Print(s.FindCommitteeByID(consensus.ShardID).Slots)
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("epoch", 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() header := consensus.ChainReader.CurrentHeader()
epoch := header.Epoch() epoch := header.Epoch()
curPubKeys := committee.WithStakingEnabled.ComputePublicKeys(
// TODO: change GetCommitteePublicKeys to read from DB
curShardState, err := committee.WithStakingEnabled.Compute(
epoch, consensus.ChainReader, epoch, consensus.ChainReader,
)
if err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error retrieving current shard state")
return Syncing
}
curPubKeys := committee.WithStakingEnabled.GetCommitteePublicKeys(
curShardState,
)[int(header.ShardID())] )[int(header.ShardID())]
consensus.numPrevPubKeys = len(curPubKeys) consensus.numPrevPubKeys = len(curPubKeys)
consensus.getLogger().Info().Msg("[UpdateConsensusInformation] Updating.....") consensus.getLogger().Info().Msg("[UpdateConsensusInformation] Updating.....")
@ -467,8 +524,20 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
consensus.SetEpochNum(epoch.Uint64() + 1) consensus.SetEpochNum(epoch.Uint64() + 1)
consensus.getLogger().Info().Uint64("headerNum", header.Number().Uint64()). consensus.getLogger().Info().Uint64("headerNum", header.Number().Uint64()).
Msg("[UpdateConsensusInformation] Epoch updated for next epoch") Msg("[UpdateConsensusInformation] Epoch updated for next epoch")
pubKeys = committee.WithStakingEnabled.ComputePublicKeys(
nextShardState, err := committee.WithStakingEnabled.Compute(
new(big.Int).Add(epoch, common.Big1), consensus.ChainReader, new(big.Int).Add(epoch, common.Big1), consensus.ChainReader,
)
if err != nil {
utils.Logger().Error().
Err(err).
Uint32("shard", consensus.ShardID).
Msg("Error retrieving next shard state")
return Syncing
}
pubKeys = committee.WithStakingEnabled.GetCommitteePublicKeys(
nextShardState,
)[int(header.ShardID())] )[int(header.ShardID())]
} else { } else {
consensus.SetEpochNum(epoch.Uint64()) consensus.SetEpochNum(epoch.Uint64())

@ -16,8 +16,8 @@ import (
var ( var (
twoThird = numeric.NewDec(2).Quo(numeric.NewDec(3)) twoThird = numeric.NewDec(2).Quo(numeric.NewDec(3))
ninetyPercent = numeric.MustNewDecFromStr("0.90") ninetyPercent = numeric.MustNewDecFromStr("0.90")
harmonysShare = numeric.MustNewDecFromStr("0.68") harmonysShare = numeric.MustNewDecFromStr("0.90") // Change back to 0.68
stakersShare = numeric.MustNewDecFromStr("0.32") stakersShare = numeric.MustNewDecFromStr("0.10") // Change back to 0.32
totalShare = numeric.MustNewDecFromStr("1.00") totalShare = numeric.MustNewDecFromStr("1.00")
) )
@ -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)

@ -1156,7 +1156,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{}{}
@ -1963,6 +1963,7 @@ func (bc *BlockChain) GetVrfByNumber(number uint64) []byte {
// GetShardState returns the shard state for the given epoch, // GetShardState returns the shard state for the given epoch,
// creating one if needed. // creating one if needed.
// TODO: [STAKING]
func (bc *BlockChain) GetShardState(epoch *big.Int) (shard.State, error) { func (bc *BlockChain) GetShardState(epoch *big.Int) (shard.State, error) {
shardState, err := bc.ReadShardState(epoch) shardState, err := bc.ReadShardState(epoch)
if err == nil { // TODO ek – distinguish ErrNotFound if err == nil { // TODO ek – distinguish ErrNotFound
@ -1971,7 +1972,7 @@ func (bc *BlockChain) GetShardState(epoch *big.Int) (shard.State, error) {
if epoch.Cmp(big.NewInt(GenesisEpoch)) == 0 { if epoch.Cmp(big.NewInt(GenesisEpoch)) == 0 {
shardState, err = committee.WithStakingEnabled.Compute( shardState, err = committee.WithStakingEnabled.Compute(
big.NewInt(GenesisEpoch), bc.Config(), nil, big.NewInt(GenesisEpoch), nil,
) )
} else { } else {
prevEpoch := new(big.Int).Sub(epoch, common.Big1) prevEpoch := new(big.Int).Sub(epoch, common.Big1)

@ -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 {

@ -486,8 +486,11 @@ 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,
)
pubKeys := committee.WithStakingEnabled.GetCommitteePublicKeys(
shardState,
)[int(shardID)] )[int(shardID)]
if len(pubKeys) == 0 { if len(pubKeys) == 0 {
utils.Logger().Error(). utils.Logger().Error().

@ -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"
) )
@ -377,51 +374,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

@ -295,13 +295,13 @@ func (w *Worker) SuperCommitteeForNextEpoch(
if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) { if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) {
nextCommittee, oops = committee.WithStakingEnabled.Compute( nextCommittee, oops = 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. // WARN When we first enable staking, this condition may not be robust by itself.
// TODO: needs to make sure beacon chain sync works.
if w.config.IsStaking(w.current.header.Epoch()) { if w.config.IsStaking(w.current.header.Epoch()) {
switch beacon.CurrentHeader().Epoch().Cmp(w.current.header.Epoch()) { switch beacon.CurrentHeader().Epoch().Cmp(w.current.header.Epoch()) {
case 1: case 1:
@ -313,7 +313,6 @@ func (w *Worker) SuperCommitteeForNextEpoch(
if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) { if shard.Schedule.IsLastBlock(w.current.header.Number().Uint64()) {
nextCommittee, oops = committee.WithStakingEnabled.Compute( nextCommittee, oops = 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,
) )
} }

@ -19,14 +19,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)
} }
// PublicKeysProvider per epoch // PublicKeysProvider per epoch
type PublicKeysProvider interface { type PublicKeysProvider interface {
ComputePublicKeys(epoch *big.Int, reader DataProvider) [][]*bls.PublicKey GetCommitteePublicKeys(superComm shard.State) [][]*bls.PublicKey
ReadPublicKeysFromDB( ReadPublicKeysFromDB(
hash common.Hash, reader DataProvider, hash common.Hash, reader DataProvider,
) ([]*bls.PublicKey, error) ) ([]*bls.PublicKey, error)
@ -123,12 +123,15 @@ 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)
utils.Logger().Print("TEST-VALIDATOR")
utils.Logger().Print(validator)
for _, delegation := range validator.Delegations { for _, delegation := range validator.Delegations {
validatorStake.Add(validatorStake, delegation.Amount) validatorStake.Add(validatorStake, delegation.Amount)
} }
utils.Logger().Print("TEST-VALIDATOR2")
utils.Logger().Print(validatorStake)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -184,13 +187,8 @@ func eposStakedCommittee(
return superComm, nil return superComm, nil
} }
// ComputePublicKeys produces publicKeys of entire supercommittee per epoch // GetCommitteePublicKeys produces publicKeys of entire supercommittee per epoch
func (def partialStakingEnabled) ComputePublicKeys( func (def partialStakingEnabled) GetCommitteePublicKeys(superComm shard.State) [][]*bls.PublicKey {
epoch *big.Int, d DataProvider,
) [][]*bls.PublicKey {
config := d.Config()
superComm, _ := def.Compute(epoch, config, d)
allIdentities := make([][]*bls.PublicKey, len(superComm)) allIdentities := make([][]*bls.PublicKey, len(superComm))
for i := range superComm { for i := range superComm {
@ -245,10 +243,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 9101 validator one1d7jfnr6yraxnrycgaemyktkmhmajhp8kl0yahv f47238daef97d60deedbde5302d05dea5de67608f11f406576e363661f7dcbc4a1385948549b31a6c70f6fde8a391486 127.0.0.1 9100 validator one1a50tun737ulcvwy0yvve0pvu5skq0kjargvhwe 52ecce5f64db21cbe374c9268188f5d2cdd5bec1a3112276a350349860e35fb81f8cfe447a311e0550d961cf25cb988d
127.0.0.1 9102 validator one1r4zyyjqrulf935a479sgqlpa78kz7zlcg2jfen fc4b9c535ee91f015efff3f32fbb9d32cdd9bfc8a837bb3eee89b8fff653c7af2050a4e147ebe5c7233dc2d5df06ee0a 127.0.0.1 9101 validator one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100
127.0.0.1 9103 validator one1p7ht2d4kl8ve7a8jxw746yfnx4wnfxtp8jqxwe ca86e551ee42adaaa6477322d7db869d3e203c00d7b86c82ebee629ad79cb6d57b8f3db28336778ec2180e56a8e07296 127.0.0.1 9102 validator one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7 678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c
127.0.0.1 9104 validator one1z05g55zamqzfw9qs432n33gycdmyvs38xjemyl 95117937cd8c09acd2dfae847d74041a67834ea88662a7cbed1e170350bc329e53db151e5a0ef3e712e35287ae954818 127.0.0.1 9103 validator one129r9pj3sk0re76f7zs3qz92rggmdgjhtwge62k 63f479f249c59f0486fda8caa2ffb247209489dae009dfde6144ff38c370230963d360dffd318cfb26c213320e89a512
127.0.0.1 9105 validator one1ljznytjyn269azvszjlcqvpcj6hjm822yrcp2e 68ae289d73332872ec8d04ac256ca0f5453c88ad392730c5741b6055bc3ec3d086ab03637713a29f459177aaa8340615 127.0.0.1 9104 validator one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc 16513c487a6bb76f37219f3c2927a4f281f9dd3fd6ed2e3a64e500de6545cf391dd973cc228d24f9bd01efe94912e714
127.0.0.1 9107 validator one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100 127.0.0.1 9105 validator one1658znfwf40epvy7e46cqrmzyy54h4n0qa73nep 576d3c48294e00d6be4a22b07b66a870ddee03052fe48a5abbd180222e5d5a1f8946a78d55b025de21635fd743bbad90
127.0.0.1 9108 validator one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7 678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c 127.0.0.1 9106 validator one1ghkz3frhske7emk79p7v2afmj4a5t0kmjyt4s5 eca09c1808b729ca56f1b5a6a287c6e1c3ae09e29ccf7efa35453471fcab07d9f73cee249e2b91f5ee44eb9618be3904
127.0.0.1 9109 validator one1658znfwf40epvy7e46cqrmzyy54h4n0qa73nep 576d3c48294e00d6be4a22b07b66a870ddee03052fe48a5abbd180222e5d5a1f8946a78d55b025de21635fd743bbad90 127.0.0.1 9107 validator one1d7jfnr6yraxnrycgaemyktkmhmajhp8kl0yahv f47238daef97d60deedbde5302d05dea5de67608f11f406576e363661f7dcbc4a1385948549b31a6c70f6fde8a391486
127.0.0.1 9110 validator one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc 16513c487a6bb76f37219f3c2927a4f281f9dd3fd6ed2e3a64e500de6545cf391dd973cc228d24f9bd01efe94912e714 127.0.0.1 9108 validator one1r4zyyjqrulf935a479sgqlpa78kz7zlcg2jfen fc4b9c535ee91f015efff3f32fbb9d32cdd9bfc8a837bb3eee89b8fff653c7af2050a4e147ebe5c7233dc2d5df06ee0a
127.0.0.1 9109 validator one1p7ht2d4kl8ve7a8jxw746yfnx4wnfxtp8jqxwe ca86e551ee42adaaa6477322d7db869d3e203c00d7b86c82ebee629ad79cb6d57b8f3db28336778ec2180e56a8e07296
127.0.0.1 9099 explorer
Loading…
Cancel
Save