Compare commits

...

6 Commits

  1. 1
      cmd/harmony/main.go
  2. 2
      consensus/checks.go
  3. 2
      consensus/consensus.go
  4. 20
      consensus/consensus_service.go
  5. 2
      consensus/consensus_v2.go
  6. 6
      consensus/construct.go
  7. 3
      consensus/enums.go
  8. 2
      consensus/leader.go
  9. 4
      consensus/validator.go
  10. 10
      consensus/view_change.go
  11. 6
      go.mod
  12. 4
      go.sum
  13. 10
      internal/configs/sharding/testnet.go
  14. 14
      internal/params/config.go
  15. 60
      internal/registry/registry.go
  16. 94
      node/addresses.go
  17. 114
      node/node.go
  18. 26
      node/node_handler.go
  19. 9
      node/node_newblock.go
  20. 2
      p2p/stream/protocols/sync/chain_test.go
  21. 2
      p2p/stream/protocols/sync/client.go
  22. 7
      p2p/stream/protocols/sync/stream.go
  23. 2
      p2p/stream/protocols/sync/stream_test.go
  24. 2
      p2p/stream/protocols/sync/utils.go
  25. 18
      test/chain/reward/main.go

@ -877,6 +877,7 @@ func setupConsensusAndNode(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfi
Uint64("viewID", viewID).
Msg("Init Blockchain")
currentNode.Consensus.Registry().SetNodeConfig(currentNode.NodeConfig)
currentConsensus.PostConsensusJob = currentNode.PostConsensusProcessing
// update consensus information based on the blockchain
currentConsensus.SetMode(currentConsensus.UpdateConsensusInformation())

@ -4,13 +4,13 @@ import (
"bytes"
"encoding/binary"
protobuf "github.com/golang/protobuf/proto"
libbls "github.com/harmony-one/bls/ffi/go/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/pkg/errors"
protobuf "google.golang.org/protobuf/proto"
)
// MaxBlockNumDiff limits the received block number to only 100 further from the current block number

@ -254,6 +254,8 @@ func (consensus *Consensus) getConsensusLeaderPrivateKey() (*bls.PrivateKeyWrapp
}
func (consensus *Consensus) IsBackup() bool {
consensus.mutex.RLock()
defer consensus.mutex.RUnlock()
return consensus.isBackup
}

@ -5,27 +5,26 @@ import (
"sync/atomic"
"time"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/multibls"
"github.com/harmony-one/harmony/webhooks"
"github.com/ethereum/go-ethereum/common"
protobuf "github.com/golang/protobuf/proto"
bls_core "github.com/harmony-one/bls/ffi/go/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/consensus/signature"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/crypto/bls"
bls_cosi "github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/harmony-one/harmony/internal/chain"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/multibls"
"github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/shard/committee"
"github.com/harmony-one/harmony/webhooks"
"github.com/pkg/errors"
"github.com/rs/zerolog"
protobuf "google.golang.org/protobuf/proto"
)
// WaitForNewRandomness listens to the RndChannel to receive new VDF randomness.
@ -191,10 +190,6 @@ func (consensus *Consensus) SetMode(m Mode) {
// SetMode sets the mode of consensus
func (consensus *Consensus) setMode(m Mode) {
if m == Normal && consensus.isBackup {
m = NormalBackup
}
consensus.getLogger().Debug().
Str("Mode", m.String()).
Msg("[SetMode]")
@ -203,11 +198,12 @@ func (consensus *Consensus) setMode(m Mode) {
// SetIsBackup sets the mode of consensus
func (consensus *Consensus) SetIsBackup(isBackup bool) {
consensus.mutex.Lock()
defer consensus.mutex.Unlock()
consensus.getLogger().Debug().
Bool("IsBackup", isBackup).
Msg("[SetIsBackup]")
consensus.isBackup = isBackup
consensus.current.SetIsBackup(isBackup)
}
// Mode returns the mode of consensus

@ -106,7 +106,7 @@ func (consensus *Consensus) HandleMessageUpdate(ctx context.Context, peer libp2p
consensus.isLeader()
// if in backup normal mode, force ignore view change event and leader event.
if consensus.current.Mode() == NormalBackup {
if consensus.isBackup {
canHandleViewChange = false
intendedForLeader = false
}

@ -4,15 +4,13 @@ import (
"bytes"
"errors"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/crypto/bls"
bls_core "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/internal/utils"
protobuf "google.golang.org/protobuf/proto"
)
// NetworkMessage is a message intended to be

@ -14,8 +14,6 @@ const (
Syncing
// Listening ..
Listening
// NormalBackup Backup Node ..
NormalBackup
)
// FBFTPhase : different phases of consensus
@ -34,7 +32,6 @@ var (
ViewChanging: "ViewChanging",
Syncing: "Syncing",
Listening: "Listening",
NormalBackup: "NormalBackup",
}
phaseNames = map[FBFTPhase]string{
FBFTAnnounce: "Announce",

@ -131,6 +131,8 @@ func (consensus *Consensus) onPrepare(recvMsg *FBFTMessage) {
signerCount := consensus.decider.SignersCount(quorum.Prepare)
//// Read - End
consensus.UpdateLeaderMetrics(float64(signerCount), float64(consensus.getBlockNum()))
// Check BLS signature for the multi-sig
prepareSig := recvMsg.Payload
var sign bls_core.Sign

@ -133,7 +133,7 @@ func (consensus *Consensus) validateNewBlock(recvMsg *FBFTMessage) (*types.Block
}
func (consensus *Consensus) prepare() {
if consensus.IsBackup() {
if consensus.isBackup {
return
}
@ -152,7 +152,7 @@ func (consensus *Consensus) prepare() {
// sendCommitMessages send out commit messages to leader
func (consensus *Consensus) sendCommitMessages(blockObj *types.Block) {
if consensus.IsBackup() || blockObj == nil {
if consensus.isBackup || blockObj == nil {
return
}

@ -33,8 +33,6 @@ type State struct {
// view changing id is used during view change mode
// it is the next view id
viewChangingID uint64
isBackup bool
}
// Mode return the current node mode
@ -44,10 +42,6 @@ func (pm *State) Mode() Mode {
// SetMode set the node mode as required
func (pm *State) SetMode(s Mode) {
if s == Normal && pm.isBackup {
s = NormalBackup
}
pm.mode = s
}
@ -81,10 +75,6 @@ func (pm *State) GetViewChangeDuraion() time.Duration {
return time.Duration(diff * diff * int64(viewChangeDuration))
}
func (pm *State) SetIsBackup(isBackup bool) {
pm.isBackup = isBackup
}
// fallbackNextViewID return the next view ID and duration when there is an exception
// to calculate the time-based viewId
func (consensus *Consensus) fallbackNextViewID() (uint64, time.Duration) {

@ -17,7 +17,7 @@ require (
github.com/ethereum/go-ethereum v1.13.4
github.com/go-redis/redis/v8 v8.11.5
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3
github.com/golang/protobuf v1.5.3 // indirect
github.com/golangci/golangci-lint v1.22.2
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
@ -68,8 +68,8 @@ require (
require (
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b
github.com/grafana/pyroscope-go v1.0.4
github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.2.3
github.com/ledgerwatch/erigon-lib v0.0.0-20230607152933-42c9c28cac68
github.com/ledgerwatch/log/v3 v3.8.0
github.com/olekukonko/tablewriter v0.0.5
@ -148,14 +148,12 @@ require (
github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect
github.com/holiman/uint256 v1.2.3 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect

@ -632,10 +632,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMHC7Bm0=
github.com/grafana/pyroscope-go v1.0.4/go.mod h1:0d7ftwSMBV/Awm7CCiYmHQEG8Y44Ma3YSjt+nWcWztY=
github.com/grafana/pyroscope-go/godeltaprof v0.1.4 h1:mDsJ3ngul7UfrHibGQpV66PbZ3q1T8glz/tK3bQKKEk=
github.com/grafana/pyroscope-go/godeltaprof v0.1.4/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko=
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=

@ -42,6 +42,8 @@ const (
func (ts testnetSchedule) InstanceForEpoch(epoch *big.Int) Instance {
switch {
case params.TestnetChainConfig.IsTestnetExternalEpoch(epoch):
return testnetV6
case params.TestnetChainConfig.IsHIP30(epoch):
return testnetV5
case params.TestnetChainConfig.IsFeeCollectEpoch(epoch):
@ -169,4 +171,12 @@ var (
hip30CollectionAddressTestnet, testnetReshardingEpoch,
TestnetSchedule.BlocksPerEpoch(),
)
testnetV6 = MustNewInstance(
2, 30, 0, 0,
numeric.MustNewDecFromStr("0.0"), genesis.TNHarmonyAccountsV1,
genesis.TNFoundationalAccounts, emptyAllowlist,
feeCollectorsTestnet, numeric.MustNewDecFromStr("0.25"),
hip30CollectionAddressTestnet, testnetReshardingEpoch,
TestnetSchedule.BlocksPerEpoch(),
)
)

@ -77,6 +77,7 @@ var (
BlockGas30MEpoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00
MaxRateEpoch: EpochTBD,
DevnetExternalEpoch: EpochTBD,
TestnetExternalEpoch: EpochTBD,
}
// TestnetChainConfig contains the chain parameters to run a node on the harmony test network.
@ -122,6 +123,7 @@ var (
BlockGas30MEpoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00
MaxRateEpoch: EpochTBD,
DevnetExternalEpoch: EpochTBD,
TestnetExternalEpoch: EpochTBD,
}
// PangaeaChainConfig contains the chain parameters for the Pangaea network.
// All features except for CrossLink are enabled at launch.
@ -167,6 +169,7 @@ var (
BlockGas30MEpoch: big.NewInt(0),
MaxRateEpoch: EpochTBD,
DevnetExternalEpoch: EpochTBD,
TestnetExternalEpoch: EpochTBD,
}
// PartnerChainConfig contains the chain parameters for the Partner network.
@ -212,6 +215,7 @@ var (
HIP30Epoch: big.NewInt(7),
BlockGas30MEpoch: big.NewInt(7),
MaxRateEpoch: EpochTBD,
TestnetExternalEpoch: EpochTBD,
DevnetExternalEpoch: big.NewInt(144),
}
@ -259,6 +263,7 @@ var (
BlockGas30MEpoch: big.NewInt(0),
MaxRateEpoch: EpochTBD,
DevnetExternalEpoch: EpochTBD,
TestnetExternalEpoch: EpochTBD,
}
// LocalnetChainConfig contains the chain parameters to run for local development.
@ -304,6 +309,7 @@ var (
BlockGas30MEpoch: big.NewInt(0),
MaxRateEpoch: EpochTBD,
DevnetExternalEpoch: EpochTBD,
TestnetExternalEpoch: EpochTBD,
}
// AllProtocolChanges ...
@ -350,6 +356,7 @@ var (
big.NewInt(0), // BlockGas30M
big.NewInt(0), // BlockGas30M
big.NewInt(0), // MaxRateEpoch
big.NewInt(0), // MaxRateEpoch
big.NewInt(0),
}
@ -397,6 +404,7 @@ var (
big.NewInt(0), // HIP30Epoch
big.NewInt(0), // BlockGas30M
big.NewInt(0), // MaxRateEpoch
big.NewInt(0), // MaxRateEpoch
big.NewInt(0),
}
@ -564,6 +572,8 @@ type ChainConfig struct {
DevnetExternalEpoch *big.Int `json:"devnet-external-epoch,omitempty"`
TestnetExternalEpoch *big.Int `json:"testnet-external-epoch,omitempty"`
BlockGas30MEpoch *big.Int `json:"block-gas-30m-epoch,omitempty"`
// MaxRateEpoch will make sure the validator max-rate is at least equal to the minRate + the validator max-rate-increase
@ -831,6 +841,10 @@ func (c *ChainConfig) IsDevnetExternalEpoch(epoch *big.Int) bool {
return isForked(c.DevnetExternalEpoch, epoch)
}
func (c *ChainConfig) IsTestnetExternalEpoch(epoch *big.Int) bool {
return isForked(c.TestnetExternalEpoch, epoch)
}
func (c *ChainConfig) IsMaxRate(epoch *big.Int) bool {
return isForked(c.MaxRateEpoch, epoch)
}

@ -3,23 +3,30 @@ package registry
import (
"sync"
"github.com/ethereum/go-ethereum/common"
bls_core "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/shardchain"
"github.com/harmony-one/harmony/multibls"
"github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/webhooks"
)
// Registry consolidates services at one place.
type Registry struct {
mu sync.Mutex
blockchain core.BlockChain
beaconchain core.BlockChain
webHooks *webhooks.Hooks
txPool *core.TxPool
cxPool *core.CxPool
isBackup bool
engine engine.Engine
collection *shardchain.CollectionImpl
mu sync.Mutex
blockchain core.BlockChain
beaconchain core.BlockChain
webHooks *webhooks.Hooks
txPool *core.TxPool
cxPool *core.CxPool
isBackup bool
engine engine.Engine
collection *shardchain.CollectionImpl
nodeConfig *nodeconfig.ConfigType
addressToBLSKey AddressToBLSKey
}
// New creates a new registry.
@ -160,3 +167,38 @@ func (r *Registry) GetShardChainCollection() *shardchain.CollectionImpl {
return r.collection
}
func (r *Registry) SetNodeConfig(n *nodeconfig.ConfigType) *Registry {
r.mu.Lock()
defer r.mu.Unlock()
r.nodeConfig = n
return r
}
func (r *Registry) GetNodeConfig() *nodeconfig.ConfigType {
r.mu.Lock()
defer r.mu.Unlock()
return r.nodeConfig
}
func (r *Registry) GetAddressToBLSKey() AddressToBLSKey {
r.mu.Lock()
defer r.mu.Unlock()
return r.addressToBLSKey
}
func (r *Registry) SetAddressToBLSKey(a AddressToBLSKey) *Registry {
r.mu.Lock()
defer r.mu.Unlock()
r.addressToBLSKey = a
return r
}
type AddressToBLSKey interface {
GetAddressForBLSKey(publicKeys multibls.PublicKeys, shardState *shard.State, blskey *bls_core.PublicKey) common.Address
GetAddresses(publicKeys multibls.PublicKeys, shardState *shard.State) map[string]common.Address
}

@ -0,0 +1,94 @@
package node
import (
"math/big"
"sync"
"github.com/ethereum/go-ethereum/common"
bls_core "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/crypto/bls"
common2 "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/internal/utils/lrucache"
"github.com/harmony-one/harmony/multibls"
"github.com/harmony-one/harmony/shard"
)
type AddressToBLSKey struct {
// KeysToAddrs holds the addresses of bls keys run by the node
keysToAddrs *lrucache.Cache[uint64, map[string]common.Address]
keysToAddrsMutex sync.Mutex
shardID uint32
}
// NewAddressToBLSKey creates a new AddressToBLSKey
func NewAddressToBLSKey(shardID uint32) *AddressToBLSKey {
return &AddressToBLSKey{
keysToAddrs: lrucache.NewCache[uint64, map[string]common.Address](100),
shardID: shardID,
}
}
// GetAddressForBLSKey retrieves the ECDSA address associated with bls key for epoch
func (a *AddressToBLSKey) GetAddressForBLSKey(publicKeys multibls.PublicKeys, shardState *shard.State, blskey *bls_core.PublicKey) common.Address {
return a.GetAddresses(publicKeys, shardState)[blskey.SerializeToHexStr()]
}
// GetAddresses retrieves all ECDSA addresses of the bls keys for epoch
func (a *AddressToBLSKey) GetAddresses(publicKeys multibls.PublicKeys, shardState *shard.State) map[string]common.Address {
// populate if new epoch
if rs, ok := a.keysToAddrs.Get(shardState.Epoch.Uint64()); ok {
return rs
}
a.keysToAddrsMutex.Lock()
a.populateSelfAddresses(publicKeys, shardState, shardState.Epoch)
a.keysToAddrsMutex.Unlock()
if rs, ok := a.keysToAddrs.Get(shardState.Epoch.Uint64()); ok {
return rs
}
return make(map[string]common.Address)
}
func (a *AddressToBLSKey) populateSelfAddresses(publicKeys multibls.PublicKeys, shardState *shard.State, epoch *big.Int) {
shardID := a.shardID
committee, err := shardState.FindCommitteeByID(shardID)
if err != nil {
utils.Logger().Error().Err(err).
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Msg("[PopulateSelfAddresses] failed to find shard committee")
return
}
keysToAddrs := map[string]common.Address{}
for _, blskey := range publicKeys {
blsStr := blskey.Bytes.Hex()
shardkey := bls.FromLibBLSPublicKeyUnsafe(blskey.Object)
if shardkey == nil {
utils.Logger().Error().
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Str("blskey", blsStr).
Msg("[PopulateSelfAddresses] failed to get shard key from bls key")
return
}
addr, err := committee.AddressForBLSKey(*shardkey)
if err != nil {
utils.Logger().Error().Err(err).
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Str("blskey", blsStr).
Msg("[PopulateSelfAddresses] could not find address")
return
}
keysToAddrs[blsStr] = *addr
utils.Logger().Debug().
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Str("bls-key", blsStr).
Str("address", common2.MustAddressToBech32(*addr)).
Msg("[PopulateSelfAddresses]")
}
a.keysToAddrs.Set(epoch.Uint64(), keysToAddrs)
}

@ -11,28 +11,9 @@ import (
"sync"
"time"
"github.com/harmony-one/harmony/internal/registry"
"github.com/harmony-one/harmony/internal/shardchain/tikv_manage"
"github.com/harmony-one/harmony/internal/tikv"
"github.com/harmony-one/harmony/internal/tikv/redis_helper"
"github.com/harmony-one/harmony/internal/utils/lrucache"
"github.com/ethereum/go-ethereum/rlp"
harmonyconfig "github.com/harmony-one/harmony/internal/configs/harmony"
"github.com/harmony-one/harmony/internal/utils/crosslinks"
"github.com/ethereum/go-ethereum/common"
protobuf "github.com/golang/protobuf/proto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/abool"
bls_core "github.com/harmony-one/bls/ffi/go/bls"
lru "github.com/hashicorp/golang-lru"
libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub"
libp2p_peer "github.com/libp2p/go-libp2p/core/peer"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/rcrowley/go-metrics"
"golang.org/x/sync/semaphore"
"github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
proto_node "github.com/harmony-one/harmony/api/proto/node"
@ -45,10 +26,15 @@ import (
"github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/crypto/bls"
common2 "github.com/harmony-one/harmony/internal/common"
harmonyconfig "github.com/harmony-one/harmony/internal/configs/harmony"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/registry"
"github.com/harmony-one/harmony/internal/shardchain/tikv_manage"
"github.com/harmony-one/harmony/internal/tikv"
"github.com/harmony-one/harmony/internal/tikv/redis_helper"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/internal/utils/crosslinks"
"github.com/harmony-one/harmony/node/worker"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/shard"
@ -56,6 +42,14 @@ import (
"github.com/harmony-one/harmony/staking/slash"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/harmony-one/harmony/webhooks"
lru "github.com/hashicorp/golang-lru"
libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub"
libp2p_peer "github.com/libp2p/go-libp2p/core/peer"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/rcrowley/go-metrics"
"golang.org/x/sync/semaphore"
protobuf "google.golang.org/protobuf/proto"
)
const (
@ -127,9 +121,7 @@ type Node struct {
// Chain configuration.
chainConfig params.ChainConfig
unixTimeAtNodeStart int64
// KeysToAddrs holds the addresses of bls keys run by the node
keysToAddrs *lrucache.Cache[uint64, map[string]common.Address]
keysToAddrsMutex sync.Mutex
// TransactionErrorSink contains error messages for any failed transaction, in memory only
TransactionErrorSink *types.TransactionErrorSink
// BroadcastInvalidTx flag is considered when adding pending tx to tx-pool
@ -1028,12 +1020,11 @@ func New(
registry *registry.Registry,
) *Node {
node := Node{
registry: registry,
registry: registry.SetAddressToBLSKey(NewAddressToBLSKey(consensusObj.ShardID)),
unixTimeAtNodeStart: time.Now().Unix(),
TransactionErrorSink: types.NewTransactionErrorSink(),
crosslinks: crosslinks.New(),
syncID: GenerateSyncID(),
keysToAddrs: lrucache.NewCache[uint64, map[string]common.Address](10),
}
if consensusObj == nil {
panic("consensusObj is nil")
@ -1302,77 +1293,6 @@ func (node *Node) ShutDown() {
os.Exit(0)
}
func (node *Node) populateSelfAddresses(epoch *big.Int) {
shardID := node.Consensus.ShardID
shardState, err := node.Consensus.Blockchain().ReadShardState(epoch)
if err != nil {
utils.Logger().Error().Err(err).
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Msg("[PopulateSelfAddresses] failed to read shard")
return
}
committee, err := shardState.FindCommitteeByID(shardID)
if err != nil {
utils.Logger().Error().Err(err).
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Msg("[PopulateSelfAddresses] failed to find shard committee")
return
}
keysToAddrs := map[string]common.Address{}
for _, blskey := range node.Consensus.GetPublicKeys() {
blsStr := blskey.Bytes.Hex()
shardkey := bls.FromLibBLSPublicKeyUnsafe(blskey.Object)
if shardkey == nil {
utils.Logger().Error().
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Str("blskey", blsStr).
Msg("[PopulateSelfAddresses] failed to get shard key from bls key")
return
}
addr, err := committee.AddressForBLSKey(*shardkey)
if err != nil {
utils.Logger().Error().Err(err).
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Str("blskey", blsStr).
Msg("[PopulateSelfAddresses] could not find address")
return
}
keysToAddrs[blsStr] = *addr
utils.Logger().Debug().
Int64("epoch", epoch.Int64()).
Uint32("shard-id", shardID).
Str("bls-key", blsStr).
Str("address", common2.MustAddressToBech32(*addr)).
Msg("[PopulateSelfAddresses]")
}
node.keysToAddrs.Set(epoch.Uint64(), keysToAddrs)
}
// GetAddressForBLSKey retrieves the ECDSA address associated with bls key for epoch
func (node *Node) GetAddressForBLSKey(blskey *bls_core.PublicKey, epoch *big.Int) common.Address {
return node.GetAddresses(epoch)[blskey.SerializeToHexStr()]
}
// GetAddresses retrieves all ECDSA addresses of the bls keys for epoch
func (node *Node) GetAddresses(epoch *big.Int) map[string]common.Address {
// populate if new epoch
if rs, ok := node.keysToAddrs.Get(epoch.Uint64()); ok {
return rs
}
node.keysToAddrsMutex.Lock()
node.populateSelfAddresses(epoch)
node.keysToAddrsMutex.Unlock()
if rs, ok := node.keysToAddrs.Get(epoch.Uint64()); ok {
return rs
}
return make(map[string]common.Address)
}
// IsRunningBeaconChain returns whether the node is running on beacon chain.
func (node *Node) IsRunningBeaconChain() bool {
return node.NodeConfig.ShardID == shard.BeaconChainShardID

@ -137,7 +137,7 @@ func (node *Node) stakingMessageHandler(msgPayload []byte) {
// BroadcastNewBlock is called by consensus leader to sync new blocks with other clients/nodes.
// NOTE: For now, just send to the client (basically not broadcasting)
// TODO (lc): broadcast the new blocks to new nodes doing state sync
func (node *Node) BroadcastNewBlock(newBlock *types.Block, nodeConfig *nodeconfig.ConfigType) {
func BroadcastNewBlock(host p2p.Host, newBlock *types.Block, nodeConfig *nodeconfig.ConfigType) {
groups := []nodeconfig.GroupID{nodeConfig.GetClientGroupID()}
utils.Logger().Info().
Msgf(
@ -146,7 +146,7 @@ func (node *Node) BroadcastNewBlock(newBlock *types.Block, nodeConfig *nodeconfi
msg := p2p.ConstructMessage(
proto_node.ConstructBlocksSyncMessage([]*types.Block{newBlock}),
)
if err := node.host.SendMessageToGroups(groups, msg); err != nil {
if err := host.SendMessageToGroups(groups, msg); err != nil {
utils.Logger().Warn().Err(err).Msg("cannot broadcast new block")
}
}
@ -330,10 +330,10 @@ func getCrosslinkHeadersForShards(shardChain core.BlockChain, curBlock *types.Bl
// 2. [leader] send cross shard tx receipts to destination shard
func (node *Node) PostConsensusProcessing(newBlock *types.Block) error {
if node.Consensus.IsLeader() {
if node.IsRunningBeaconChain() {
if IsRunningBeaconChain(node.Consensus) {
// TODO: consider removing this and letting other nodes broadcast new blocks.
// But need to make sure there is at least 1 node that will do the job.
node.BroadcastNewBlock(newBlock, node.NodeConfig)
BroadcastNewBlock(node.host, newBlock, node.NodeConfig)
}
BroadcastCXReceipts(newBlock, node.Consensus)
} else {
@ -361,8 +361,8 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) error {
rnd := rand.Intn(100)
if rnd < 1 {
// Beacon validators also broadcast new blocks to make sure beacon sync is strong.
if node.IsRunningBeaconChain() {
node.BroadcastNewBlock(newBlock, node.NodeConfig)
if IsRunningBeaconChain(node.Consensus) {
BroadcastNewBlock(node.host, newBlock, node.NodeConfig)
}
BroadcastCXReceipts(newBlock, node.Consensus)
}
@ -374,7 +374,15 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) error {
if h := node.NodeConfig.WebHooks.Hooks; h != nil {
if h.Availability != nil {
for _, addr := range node.GetAddresses(newBlock.Epoch()) {
shardState, err := node.Blockchain().ReadShardState(newBlock.Epoch())
if err != nil {
utils.Logger().Error().Err(err).
Int64("epoch", newBlock.Epoch().Int64()).
Uint32("shard-id", node.Consensus.ShardID).
Msg("failed to read shard state")
return err
}
for _, addr := range node.Consensus.Registry().GetAddressToBLSKey().GetAddresses(node.Consensus.GetPublicKeys(), shardState) {
wrapper, err := node.Beaconchain().ReadValidatorInformation(addr)
if err != nil {
utils.Logger().Err(err).Str("addr", addr.Hex()).Msg("failed reaching validator info")
@ -404,6 +412,10 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) error {
return nil
}
func IsRunningBeaconChain(c *consensus.Consensus) bool {
return c.ShardID == shard.BeaconChainShardID
}
// BootstrapConsensus is a goroutine to check number of peers and start the consensus
func (node *Node) BootstrapConsensus() error {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)

@ -123,11 +123,15 @@ func (node *Node) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error)
if err != nil {
return nil, errors.Wrap(err, "failed to update worker")
}
header := env.CurrentHeader()
shardState, err := node.Blockchain().ReadShardState(header.Epoch())
if err != nil {
return nil, errors.WithMessage(err, "failed to read shard")
}
var (
header = env.CurrentHeader()
leaderKey = node.Consensus.GetLeaderPubKey()
coinbase = node.GetAddressForBLSKey(leaderKey.Object, header.Epoch())
coinbase = node.registry.GetAddressToBLSKey().GetAddressForBLSKey(node.Consensus.GetPublicKeys(), shardState, leaderKey.Object)
beneficiary = coinbase
)
@ -293,7 +297,6 @@ func (node *Node) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error)
node.Worker.ApplyShardReduction()
// Prepare shard state
var shardState *shard.State
if shardState, err = node.Blockchain().SuperCommitteeForNextEpoch(
node.Beaconchain(), node.Worker.GetCurrentHeader(), false,
); err != nil {

@ -11,11 +11,11 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
syncpb "github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
protobuf "google.golang.org/protobuf/proto"
)
type testChainHelper struct{}

@ -8,12 +8,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
syncpb "github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
sttypes "github.com/harmony-one/harmony/p2p/stream/types"
"github.com/pkg/errors"
protobuf "google.golang.org/protobuf/proto"
)
// GetBlocksByNumber do getBlocksByNumberRequest through sync stream protocol.

@ -5,17 +5,16 @@ import (
"sync/atomic"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
syncpb "github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
sttypes "github.com/harmony-one/harmony/p2p/stream/types"
libp2p_network "github.com/libp2p/go-libp2p/core/network"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/rs/zerolog"
protobuf "google.golang.org/protobuf/proto"
)
// syncStream is the structure for a stream running sync protocol.
@ -84,7 +83,7 @@ func (st *syncStream) readMsgLoop() {
func (st *syncStream) deliverMsg(msg protobuf.Message) {
syncMsg := msg.(*syncpb.Message)
if syncMsg == nil {
st.logger.Info().Str("message", msg.String()).Msg("received unexpected sync message")
st.logger.Info().Interface("message", msg).Msg("received unexpected sync message")
return
}
if req := syncMsg.GetReq(); req != nil {

@ -7,7 +7,6 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
protobuf "github.com/golang/protobuf/proto"
syncpb "github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
sttypes "github.com/harmony-one/harmony/p2p/stream/types"
ic "github.com/libp2p/go-libp2p/core/crypto"
@ -15,6 +14,7 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
ma "github.com/multiformats/go-multiaddr"
protobuf "google.golang.org/protobuf/proto"
)
var _ sttypes.Protocol = &Protocol{}

@ -3,10 +3,10 @@ package sync
import (
"fmt"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/p2p/stream/common/requestmanager"
syncpb "github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
"github.com/pkg/errors"
protobuf "google.golang.org/protobuf/proto"
)
var (

@ -6,28 +6,24 @@ import (
"math/rand"
"time"
"github.com/harmony-one/harmony/core/rawdb"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/crypto/bls"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils"
common2 "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
bls_core "github.com/harmony-one/bls/ffi/go/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/harmony-one/harmony/internal/chain"
"github.com/harmony-one/harmony/internal/common"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric"
staking "github.com/harmony-one/harmony/staking/types"
protobuf "google.golang.org/protobuf/proto"
)
var (

Loading…
Cancel
Save