From cbb62fd89afc0f71f2c2d441cba027eb4fc38f8b Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:16:11 -0500 Subject: [PATCH 01/66] Updated protobuf from outdated github.com/golang/protobuf to google.golang.org/protobuf. (#4636) --- consensus/checks.go | 2 +- consensus/consensus_service.go | 13 ++++----- consensus/construct.go | 6 ++-- node/node.go | 35 +++++++++++------------- p2p/stream/protocols/sync/chain_test.go | 2 +- p2p/stream/protocols/sync/client.go | 2 +- p2p/stream/protocols/sync/stream.go | 7 ++--- p2p/stream/protocols/sync/stream_test.go | 2 +- p2p/stream/protocols/sync/utils.go | 2 +- test/chain/reward/main.go | 18 +++++------- 10 files changed, 39 insertions(+), 50 deletions(-) diff --git a/consensus/checks.go b/consensus/checks.go index 32f59fb938..b4e1d12075 100644 --- a/consensus/checks.go +++ b/consensus/checks.go @@ -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 diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index 48324c4788..1ba1f6e2fd 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -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. diff --git a/consensus/construct.go b/consensus/construct.go index 48291a3644..01d02a4d41 100644 --- a/consensus/construct.go +++ b/consensus/construct.go @@ -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 diff --git a/node/node.go b/node/node.go index f80c502a0a..d8a8e8e6fd 100644 --- a/node/node.go +++ b/node/node.go @@ -11,28 +11,10 @@ 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" @@ -46,9 +28,16 @@ import ( "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/internal/utils/lrucache" "github.com/harmony-one/harmony/node/worker" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/shard" @@ -56,6 +45,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 ( diff --git a/p2p/stream/protocols/sync/chain_test.go b/p2p/stream/protocols/sync/chain_test.go index 414492054c..eb153023cc 100644 --- a/p2p/stream/protocols/sync/chain_test.go +++ b/p2p/stream/protocols/sync/chain_test.go @@ -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{} diff --git a/p2p/stream/protocols/sync/client.go b/p2p/stream/protocols/sync/client.go index 45707e1191..9ae9d5c8f8 100644 --- a/p2p/stream/protocols/sync/client.go +++ b/p2p/stream/protocols/sync/client.go @@ -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. diff --git a/p2p/stream/protocols/sync/stream.go b/p2p/stream/protocols/sync/stream.go index 3077a8a135..2f2468404b 100644 --- a/p2p/stream/protocols/sync/stream.go +++ b/p2p/stream/protocols/sync/stream.go @@ -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 { diff --git a/p2p/stream/protocols/sync/stream_test.go b/p2p/stream/protocols/sync/stream_test.go index 3b538c14b8..f2e5462893 100644 --- a/p2p/stream/protocols/sync/stream_test.go +++ b/p2p/stream/protocols/sync/stream_test.go @@ -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{} diff --git a/p2p/stream/protocols/sync/utils.go b/p2p/stream/protocols/sync/utils.go index da781c23f0..d4ca224294 100644 --- a/p2p/stream/protocols/sync/utils.go +++ b/p2p/stream/protocols/sync/utils.go @@ -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 ( diff --git a/test/chain/reward/main.go b/test/chain/reward/main.go index 17be3b2715..aee4c4ed0e 100644 --- a/test/chain/reward/main.go +++ b/test/chain/reward/main.go @@ -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 ( From 56ad3fa6b91877d5b030fc39a4b89c575e9c914f Mon Sep 17 00:00:00 2001 From: Diego Nava <8563843+diego1q2w@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:52:51 +0100 Subject: [PATCH 02/66] add hardfork to make testnet external (#4640) * add hardfork to make devnet external * add hardfork to make devnet external --- internal/configs/sharding/testnet.go | 10 ++++++++++ internal/params/config.go | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/internal/configs/sharding/testnet.go b/internal/configs/sharding/testnet.go index 7c2994071c..f640857537 100644 --- a/internal/configs/sharding/testnet.go +++ b/internal/configs/sharding/testnet.go @@ -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(), + ) ) diff --git a/internal/params/config.go b/internal/params/config.go index b0c6c70d11..99c846b69a 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -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) } From 8d2b36d7f66a028f19eb3e7b1b0b64e9ec79be3a Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:53:12 -0500 Subject: [PATCH 03/66] Got rid of redundant logic with isBackup. (#4639) --- consensus/consensus.go | 2 ++ consensus/consensus_service.go | 7 ++----- consensus/consensus_v2.go | 2 +- consensus/enums.go | 3 --- consensus/validator.go | 4 ++-- consensus/view_change.go | 10 ---------- 6 files changed, 7 insertions(+), 21 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 6f019b2a9b..63f18a85e8 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -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 } diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index 1ba1f6e2fd..d658fe83d6 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -190,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]") @@ -202,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 diff --git a/consensus/consensus_v2.go b/consensus/consensus_v2.go index 0aec2537b4..33ba54b1d1 100644 --- a/consensus/consensus_v2.go +++ b/consensus/consensus_v2.go @@ -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 } diff --git a/consensus/enums.go b/consensus/enums.go index a8c4357c2a..41eafba863 100644 --- a/consensus/enums.go +++ b/consensus/enums.go @@ -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", diff --git a/consensus/validator.go b/consensus/validator.go index fa5cdac921..2f14f76b42 100644 --- a/consensus/validator.go +++ b/consensus/validator.go @@ -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 } diff --git a/consensus/view_change.go b/consensus/view_change.go index 1171b073e0..f55c5400fc 100644 --- a/consensus/view_change.go +++ b/consensus/view_change.go @@ -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) { From fa5efdc5dc2e7c5f839dbcf12063d05622d36cda Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:53:27 -0500 Subject: [PATCH 04/66] Send sings count from leader to prometheus. (#4638) --- consensus/leader.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/consensus/leader.go b/consensus/leader.go index 5740493024..4a227fa62d 100644 --- a/consensus/leader.go +++ b/consensus/leader.go @@ -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 From c32319c37788134325d2914ab18d60e76bff728c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CGheisMohammadi=E2=80=9D?= <36589218+GheisMohammadi@users.noreply.github.com> Date: Mon, 11 Mar 2024 08:23:33 +0100 Subject: [PATCH 05/66] set SnapshotLimit to zero by default for all networks --- cmd/harmony/config.go | 8 +++++++- cmd/harmony/flags_test.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/harmony/config.go b/cmd/harmony/config.go index 037221835c..0b798551ae 100644 --- a/cmd/harmony/config.go +++ b/cmd/harmony/config.go @@ -161,9 +161,15 @@ func getDefaultCacheConfig(nt nodeconfig.NetworkType) harmonyconfig.CacheConfig case nodeconfig.Mainnet: cacheConfig.Disabled = true cacheConfig.Preimages = true + cacheConfig.SnapshotLimit = 0 case nodeconfig.Testnet: - cacheConfig.Disabled = false + cacheConfig.Disabled = true + cacheConfig.Preimages = true + cacheConfig.SnapshotLimit = 0 + case nodeconfig.Partner: + cacheConfig.Disabled = true cacheConfig.Preimages = true + cacheConfig.SnapshotLimit = 0 case nodeconfig.Localnet: cacheConfig.Disabled = false cacheConfig.Preimages = false diff --git a/cmd/harmony/flags_test.go b/cmd/harmony/flags_test.go index ffe261b39a..50ed02fa29 100644 --- a/cmd/harmony/flags_test.go +++ b/cmd/harmony/flags_test.go @@ -1440,7 +1440,7 @@ func TestCacheFlags(t *testing.T) { TrieNodeLimit: defaultCacheConfig.TrieNodeLimit, TriesInMemory: defaultCacheConfig.TriesInMemory, TrieTimeLimit: defaultCacheConfig.TrieTimeLimit, - SnapshotLimit: defaultCacheConfig.SnapshotLimit, + SnapshotLimit: 0, // based on network type, SnapshotWait: defaultCacheConfig.SnapshotWait, Preimages: defaultCacheConfig.Preimages, // based on network type SnapshotNoBuild: defaultCacheConfig.SnapshotNoBuild, From 12b84f3024e9b96661c26f38980b4be07be062a8 Mon Sep 17 00:00:00 2001 From: Diego Nava <8563843+diego1q2w@users.noreply.github.com> Date: Thu, 28 Mar 2024 08:21:16 +0100 Subject: [PATCH 06/66] Enable testnet leader rotation and external (#4649) * enable leader rotation and testnet external epochs --- internal/params/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/params/config.go b/internal/params/config.go index 99c846b69a..f1b747f6dd 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -115,15 +115,15 @@ var ( ChainIdFixEpoch: big.NewInt(0), CrossShardXferPrecompileEpoch: big.NewInt(2), AllowlistEpoch: big.NewInt(2), - LeaderRotationInternalValidatorsEpoch: EpochTBD, - LeaderRotationExternalValidatorsEpoch: EpochTBD, + LeaderRotationInternalValidatorsEpoch: big.NewInt(3044), + LeaderRotationExternalValidatorsEpoch: big.NewInt(3044), FeeCollectEpoch: big.NewInt(1296), // 2023-04-28 07:14:20+00:00 ValidatorCodeFixEpoch: big.NewInt(1296), // 2023-04-28 07:14:20+00:00 HIP30Epoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00 BlockGas30MEpoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00 MaxRateEpoch: EpochTBD, DevnetExternalEpoch: EpochTBD, - TestnetExternalEpoch: EpochTBD, + TestnetExternalEpoch: big.NewInt(3044), } // PangaeaChainConfig contains the chain parameters for the Pangaea network. // All features except for CrossLink are enabled at launch. From eb468b9ad2382e5b082321db070de55f0a1dbb4b Mon Sep 17 00:00:00 2001 From: Diego Nava <8563843+diego1q2w@users.noreply.github.com> Date: Tue, 2 Apr 2024 04:00:19 +0200 Subject: [PATCH 07/66] bring back the lost maxRate epochs (#4648) * bring back the lost maxRate epochs * fix epoch testnet --- internal/params/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/params/config.go b/internal/params/config.go index f1b747f6dd..421ae3223c 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -75,7 +75,7 @@ var ( ValidatorCodeFixEpoch: big.NewInt(1535), // 2023-07-20 05:51:07+00:00 HIP30Epoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00 BlockGas30MEpoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00 - MaxRateEpoch: EpochTBD, + MaxRateEpoch: big.NewInt(1733), // 2023-12-17 12:20:15+00:00 DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, } @@ -121,7 +121,7 @@ var ( ValidatorCodeFixEpoch: big.NewInt(1296), // 2023-04-28 07:14:20+00:00 HIP30Epoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00 BlockGas30MEpoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00 - MaxRateEpoch: EpochTBD, + MaxRateEpoch: big.NewInt(2520), // 2023-12-16 12:17:14+00:00 DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: big.NewInt(3044), } From 7a6a801563409bd5f6fdbf9480d4b08bb6e5da6d Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:44:24 -0400 Subject: [PATCH 08/66] Additional logging on a block proposing. (#4658) --- consensus/consensus.go | 18 ++++++++++++++---- consensus/consensus_service.go | 2 +- consensus/consensus_v2.go | 8 ++++---- consensus/view_change.go | 2 +- internal/utils/utils.go | 6 +++--- node/node_newblock.go | 7 ++++--- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 63f18a85e8..4440fe9780 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -31,6 +31,16 @@ const ( var errLeaderPriKeyNotFound = errors.New("leader private key not found locally") +type Proposal struct { + Type ProposalType + Caller string +} + +// NewProposal creates a new proposal +func NewProposal(t ProposalType) Proposal { + return Proposal{Type: t, Caller: utils.GetCallStackInfo(2)} +} + // ProposalType is to indicate the type of signal for new block proposal type ProposalType byte @@ -90,7 +100,7 @@ type Consensus struct { // ViewChange struct vc *viewChange // Signal channel for proposing a new block and start new consensus - readySignal chan ProposalType + readySignal chan Proposal // Channel to send full commit signatures to finish new block proposal commitSigChannel chan []byte // The post-consensus job func passed from Node object @@ -151,11 +161,11 @@ func (consensus *Consensus) ChainReader() engine.ChainReader { return consensus.Blockchain() } -func (consensus *Consensus) ReadySignal(p ProposalType) { +func (consensus *Consensus) ReadySignal(p Proposal) { consensus.readySignal <- p } -func (consensus *Consensus) GetReadySignal() chan ProposalType { +func (consensus *Consensus) GetReadySignal() chan Proposal { return consensus.readySignal } @@ -304,7 +314,7 @@ func New( // displayed on explorer as Height right now consensus.setCurBlockViewID(0) consensus.SlashChan = make(chan slash.Record) - consensus.readySignal = make(chan ProposalType) + consensus.readySignal = make(chan Proposal) consensus.commitSigChannel = make(chan []byte) // channel for receiving newly generated VDF consensus.RndChannel = make(chan [vdfAndSeedSize]byte) diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index d658fe83d6..873606ca60 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -459,7 +459,7 @@ func (consensus *Consensus) updateConsensusInformation() Mode { consensus.GetLogger().Info(). Str("myKey", myPubKeys.SerializeToHexStr()). Msg("[UpdateConsensusInformation] I am the New Leader") - consensus.ReadySignal(SyncProposal) + consensus.ReadySignal(NewProposal(SyncProposal)) }() } return Normal diff --git a/consensus/consensus_v2.go b/consensus/consensus_v2.go index 33ba54b1d1..822d239001 100644 --- a/consensus/consensus_v2.go +++ b/consensus/consensus_v2.go @@ -258,7 +258,7 @@ func (consensus *Consensus) finalCommit() { // No pipelining go func() { consensus.getLogger().Info().Msg("[finalCommit] sending block proposal signal") - consensus.ReadySignal(SyncProposal) + consensus.ReadySignal(NewProposal(SyncProposal)) }() } else { // pipelining @@ -334,7 +334,7 @@ func (consensus *Consensus) StartChannel() { consensus.start = true consensus.getLogger().Info().Time("time", time.Now()).Msg("[ConsensusMainLoop] Send ReadySignal") consensus.mutex.Unlock() - consensus.ReadySignal(SyncProposal) + consensus.ReadySignal(NewProposal(SyncProposal)) return } consensus.mutex.Unlock() @@ -586,7 +586,7 @@ func (consensus *Consensus) preCommitAndPropose(blk *types.Block) error { // Send signal to Node to propose the new block for consensus consensus.getLogger().Info().Msg("[preCommitAndPropose] sending block proposal signal") consensus.mutex.Unlock() - consensus.ReadySignal(AsyncProposal) + consensus.ReadySignal(NewProposal(AsyncProposal)) }() return nil @@ -814,7 +814,7 @@ func (consensus *Consensus) setupForNewConsensus(blk *types.Block, committedMsg blockPeriod := consensus.BlockPeriod go func() { <-time.After(blockPeriod) - consensus.ReadySignal(SyncProposal) + consensus.ReadySignal(NewProposal(SyncProposal)) }() } } diff --git a/consensus/view_change.go b/consensus/view_change.go index f55c5400fc..5525e12266 100644 --- a/consensus/view_change.go +++ b/consensus/view_change.go @@ -429,7 +429,7 @@ func (consensus *Consensus) onViewChange(recvMsg *FBFTMessage) { consensus.getLogger().Error().Err(err).Msg("[onViewChange] startNewView failed") return } - go consensus.ReadySignal(SyncProposal) + go consensus.ReadySignal(NewProposal(SyncProposal)) return } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 33cf09ecad..f23b64f51c 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -92,9 +92,9 @@ func GetCallStackInfo(depthList ...int) string { } else { depth = depthList[0] } - function, file, line, _ := runtime.Caller(depth) - return fmt.Sprintf("File: %s Function: %s Line: %d", - chopPath(file), runtime.FuncForPC(function).Name(), line, + _, file, line, _ := runtime.Caller(depth) + return fmt.Sprintf("%s:%d", + file, line, ) } diff --git a/node/node_newblock.go b/node/node_newblock.go index bafb340a80..c00a8cd414 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -48,12 +48,13 @@ func (node *Node) WaitForConsensusReadyV2(cs *consensus.Consensus, stopChan chan utils.Logger().Warn(). Msg("Consensus new block proposal: STOPPED!") return - case proposalType := <-cs.GetReadySignal(): + case proposal := <-cs.GetReadySignal(): for retryCount := 0; retryCount < 3 && cs.IsLeader(); retryCount++ { time.Sleep(SleepPeriod) utils.Logger().Info(). Uint64("blockNum", cs.Blockchain().CurrentBlock().NumberU64()+1). - Bool("asyncProposal", proposalType == consensus.AsyncProposal). + Bool("asyncProposal", proposal.Type == consensus.AsyncProposal). + Str("called", proposal.Caller). Msg("PROPOSING NEW BLOCK ------------------------------------------------") // Prepare last commit signatures @@ -61,7 +62,7 @@ func (node *Node) WaitForConsensusReadyV2(cs *consensus.Consensus, stopChan chan go func() { waitTime := 0 * time.Second - if proposalType == consensus.AsyncProposal { + if proposal.Type == consensus.AsyncProposal { waitTime = consensus.CommitSigReceiverTimeout } select { From 587d2f01f6aed9accff98703ff5349e1b997d260 Mon Sep 17 00:00:00 2001 From: "Nita Neou (Soph)" Date: Tue, 23 Apr 2024 17:09:10 +0700 Subject: [PATCH 09/66] Update devnet internal vote power back to 90% --- internal/configs/sharding/partner.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internal/configs/sharding/partner.go b/internal/configs/sharding/partner.go index bbf5dccb4a..7fb9743ab6 100644 --- a/internal/configs/sharding/partner.go +++ b/internal/configs/sharding/partner.go @@ -40,6 +40,8 @@ const ( func (ps partnerSchedule) InstanceForEpoch(epoch *big.Int) Instance { switch { + case epoch.Cmp(big.NewInt(2207)) >= 0: // one time fix for devnet shard 1 down, estimated 24 April 4:30AM UTC + return partnerV3_1 case params.PartnerChainConfig.IsDevnetExternalEpoch(epoch): return partnerV3 case params.PartnerChainConfig.IsHIP30(epoch): @@ -121,3 +123,12 @@ var partnerV3 = MustNewInstance( hip30CollectionAddressTestnet, partnerReshardingEpoch, PartnerSchedule.BlocksPerEpoch(), ) + +var partnerV3_1 = MustNewInstance( + 2, 20, 4, 0, + numeric.MustNewDecFromStr("0.9"), genesis.TNHarmonyAccounts, + genesis.TNFoundationalAccounts, emptyAllowlist, + feeCollectorsDevnet[1], numeric.MustNewDecFromStr("0.25"), + hip30CollectionAddressTestnet, partnerReshardingEpoch, + PartnerSchedule.BlocksPerEpoch(), +) From 782eb4f7561ebcdfb6ca218a655c043eabf9b4b2 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Wed, 24 Apr 2024 23:52:32 -0400 Subject: [PATCH 10/66] Additional logs and cleanup. (#4656) * Additional logs and cleanup. * Fixed tests. --- consensus/consensus_msg_sender.go | 2 +- consensus/consensus_service.go | 5 +++-- consensus/leader.go | 4 ++-- consensus/validator.go | 19 +++++++++++++++---- consensus/votepower/roster.go | 26 +++++++++++--------------- crypto/bls/bls.go | 5 +++++ internal/chain/reward.go | 3 +-- staking/availability/measure.go | 4 +--- staking/availability/measure_test.go | 2 +- 9 files changed, 40 insertions(+), 30 deletions(-) diff --git a/consensus/consensus_msg_sender.go b/consensus/consensus_msg_sender.go index ffa9d8b1c6..ad32b91ce3 100644 --- a/consensus/consensus_msg_sender.go +++ b/consensus/consensus_msg_sender.go @@ -121,7 +121,7 @@ func (sender *MessageSender) Retry(msgRetry *MessageRetry) { msgRetry.retryCount++ if err := sender.host.SendMessageToGroups(msgRetry.groups, msgRetry.p2pMsg); err != nil { - utils.Logger().Warn().Str("groupID[0]", msgRetry.groups[0].String()).Uint64("blockNum", msgRetry.blockNum).Str("MsgType", msgRetry.msgType.String()).Int("RetryCount", msgRetry.retryCount).Msg("[Retry] Failed re-sending consensus message") + utils.Logger().Warn().Str("groupID[0]", msgRetry.groups[0].String()).Uint64("blockNum", msgRetry.blockNum).Str("MsgType", msgRetry.msgType.String()).Int("RetryCount", msgRetry.retryCount).Err(err).Msg("[Retry] Failed re-sending consensus message") } else { utils.Logger().Info().Str("groupID[0]", msgRetry.groups[0].String()).Uint64("blockNum", msgRetry.blockNum).Str("MsgType", msgRetry.msgType.String()).Int("RetryCount", msgRetry.retryCount).Msg("[Retry] Successfully resent consensus message") } diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index 873606ca60..89276c4540 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -435,7 +435,7 @@ func (consensus *Consensus) updateConsensusInformation() Mode { } else { consensus.getLogger().Info(). Str("leaderPubKey", leaderPubKey.Bytes.Hex()). - Msg("[UpdateConsensusInformation] Most Recent LeaderPubKey Updated Based on BlockChain") + Msgf("[UpdateConsensusInformation] Most Recent LeaderPubKey Updated Based on BlockChain, blocknum: %d", curHeader.NumberU64()) consensus.LeaderPubKey = leaderPubKey } } @@ -466,7 +466,7 @@ func (consensus *Consensus) updateConsensusInformation() Mode { } } consensus.getLogger().Info(). - Msg("[UpdateConsensusInformation] not in committee, Listening") + Msgf("[UpdateConsensusInformation] not in committee, keys len %d Listening", len(pubKeys)) // not in committee return Listening @@ -652,6 +652,7 @@ func (consensus *Consensus) GetLogger() *zerolog.Logger { // getLogger returns logger for consensus contexts added func (consensus *Consensus) getLogger() *zerolog.Logger { logger := utils.Logger().With(). + Uint32("shardID", consensus.ShardID). Uint64("myBlock", consensus.blockNum). Uint64("myViewID", consensus.getCurBlockViewID()). Str("phase", consensus.phase.String()). diff --git a/consensus/leader.go b/consensus/leader.go index 4a227fa62d..d851668aa8 100644 --- a/consensus/leader.go +++ b/consensus/leader.go @@ -82,12 +82,12 @@ func (consensus *Consensus) announce(block *types.Block) { Str("groupID", string(nodeconfig.NewGroupIDByShardID( nodeconfig.ShardID(consensus.ShardID), ))). - Msg("[Announce] Cannot send announce message") + Msgf("[Announce] Cannot send announce message with message signer %s", key.Pub.Hex()) } else { consensus.getLogger().Info(). Str("blockHash", block.Hash().Hex()). Uint64("blockNum", block.NumberU64()). - Msg("[Announce] Sent Announce Message!!") + Msgf("[Announce] Sent Announce Message with message signer %s", key.Pub.Hex()) } consensus.switchPhase("Announce", FBFTPrepare) diff --git a/consensus/validator.go b/consensus/validator.go index 2f14f76b42..14f4b52167 100644 --- a/consensus/validator.go +++ b/consensus/validator.go @@ -137,7 +137,11 @@ func (consensus *Consensus) prepare() { return } - priKeys := consensus.getPriKeysInCommittee() + priKeys, err := consensus.getPriKeysInCommittee() + if err != nil { + consensus.getLogger().Warn().Err(err).Msg("[OnAnnounce] Cannot get priKey in committee") + return + } p2pMsgs := consensus.constructP2pMessages(msg_pb.MessageType_PREPARE, nil, priKeys) @@ -156,7 +160,11 @@ func (consensus *Consensus) sendCommitMessages(blockObj *types.Block) { return } - priKeys := consensus.getPriKeysInCommittee() + priKeys, err := consensus.getPriKeysInCommittee() + if err != nil { + consensus.getLogger().Warn().Err(err).Msg("[sendCommitMessages] Cannot get priKey in committee") + return + } // Sign commit signature on the received block and construct the p2p messages commitPayload := signature.ConstructCommitPayload(consensus.Blockchain().Config(), @@ -392,7 +400,10 @@ func (consensus *Consensus) onCommitted(recvMsg *FBFTMessage) { // Collect private keys that are part of the current committee. // TODO: cache valid private keys and only update when keys change. -func (consensus *Consensus) getPriKeysInCommittee() []*bls.PrivateKeyWrapper { +func (consensus *Consensus) getPriKeysInCommittee() ([]*bls.PrivateKeyWrapper, error) { + if len(consensus.priKey) == 0 { + return nil, errors.New("no private keys in the committee") + } priKeys := []*bls.PrivateKeyWrapper{} for i, key := range consensus.priKey { if !consensus.isValidatorInCommittee(key.Pub.Bytes) { @@ -400,7 +411,7 @@ func (consensus *Consensus) getPriKeysInCommittee() []*bls.PrivateKeyWrapper { } priKeys = append(priKeys, &consensus.priKey[i]) } - return priKeys + return priKeys, nil } func (consensus *Consensus) constructP2pMessages(msgType msg_pb.MessageType, payloadForSign []byte, priKeys []*bls.PrivateKeyWrapper) []*NetworkMessage { diff --git a/consensus/votepower/roster.go b/consensus/votepower/roster.go index bebd90bbaa..96a3ac9c6b 100644 --- a/consensus/votepower/roster.go +++ b/consensus/votepower/roster.go @@ -90,19 +90,16 @@ func (v AccommodateHarmonyVote) String() string { return string(s) } -type topLevelRegistry struct { - OurVotingPowerTotalPercentage numeric.Dec - TheirVotingPowerTotalPercentage numeric.Dec - TotalEffectiveStake numeric.Dec - HMYSlotCount int64 -} - // Roster .. type Roster struct { - Voters map[bls.SerializedPublicKey]*AccommodateHarmonyVote - topLevelRegistry + Voters map[bls.SerializedPublicKey]*AccommodateHarmonyVote ShardID uint32 OrderedSlots []bls.SerializedPublicKey + + OurVotingPowerTotalPercentage numeric.Dec + TheirVotingPowerTotalPercentage numeric.Dec + TotalEffectiveStake numeric.Dec + HMYSlotCount int64 } func (r Roster) String() string { @@ -244,13 +241,12 @@ func Compute(subComm *shard.Committee, epoch *big.Int) (*Roster, error) { func NewRoster(shardID uint32) *Roster { m := map[bls.SerializedPublicKey]*AccommodateHarmonyVote{} return &Roster{ - Voters: m, - topLevelRegistry: topLevelRegistry{ - OurVotingPowerTotalPercentage: numeric.ZeroDec(), - TheirVotingPowerTotalPercentage: numeric.ZeroDec(), - TotalEffectiveStake: numeric.ZeroDec(), - }, + Voters: m, ShardID: shardID, + + OurVotingPowerTotalPercentage: numeric.ZeroDec(), + TheirVotingPowerTotalPercentage: numeric.ZeroDec(), + TotalEffectiveStake: numeric.ZeroDec(), } } diff --git a/crypto/bls/bls.go b/crypto/bls/bls.go index 7a8159ef87..4b6fe593bc 100644 --- a/crypto/bls/bls.go +++ b/crypto/bls/bls.go @@ -32,6 +32,11 @@ type PublicKeyWrapper struct { Object *bls.PublicKey } +// Hex returns the hex string of the public key +func (pk *PublicKeyWrapper) Hex() string { + return pk.Bytes.Hex() +} + // WrapperFromPrivateKey makes a PrivateKeyWrapper from bls secret key func WrapperFromPrivateKey(pri *bls.SecretKey) PrivateKeyWrapper { pub := pri.GetPublicKey() diff --git a/internal/chain/reward.go b/internal/chain/reward.go index c64199a20c..42212d6db2 100644 --- a/internal/chain/reward.go +++ b/internal/chain/reward.go @@ -511,7 +511,6 @@ func distributeRewardBeforeAggregateEpoch(bc engine.ChainReader, state *state.DB subComm := shard.Committee{ShardID: shard.BeaconChainShardID, Slots: members} if err := availability.IncrementValidatorSigningCounts( - beaconChain, subComm.StakedValidators(), state, payable, @@ -599,7 +598,7 @@ func processOneCrossLink(bc engine.ChainReader, state *state.DB, cxLink types.Cr staked := subComm.StakedValidators() startTimeLocal = time.Now() if err := availability.IncrementValidatorSigningCounts( - bc, staked, state, payableSigners, missing, + staked, state, payableSigners, missing, ); err != nil { return nil, nil, err } diff --git a/staking/availability/measure.go b/staking/availability/measure.go index 6bf36bfb05..575c804380 100644 --- a/staking/availability/measure.go +++ b/staking/availability/measure.go @@ -92,7 +92,6 @@ type signerKind struct { } func bumpCount( - bc Reader, state ValidatorState, signers []signerKind, stakedAddrSet map[common.Address]struct{}, @@ -129,13 +128,12 @@ func bumpCount( // IncrementValidatorSigningCounts .. func IncrementValidatorSigningCounts( - bc Reader, staked *shard.StakedSlots, state ValidatorState, signers, missing shard.SlotList, ) error { return bumpCount( - bc, state, []signerKind{{false, missing}, {true, signers}}, + state, []signerKind{{false, missing}, {true, signers}}, staked.LookupSet, ) } diff --git a/staking/availability/measure_test.go b/staking/availability/measure_test.go index 9a35ad80eb..393d19bb4f 100644 --- a/staking/availability/measure_test.go +++ b/staking/availability/measure_test.go @@ -158,7 +158,7 @@ func TestIncrementValidatorSigningCounts(t *testing.T) { if err != nil { t.Fatal(err) } - if err := IncrementValidatorSigningCounts(nil, ctx.staked, ctx.state, ctx.signers, + if err := IncrementValidatorSigningCounts(ctx.staked, ctx.state, ctx.signers, ctx.missings); err != nil { t.Fatal(err) From 0e29f522fb722841d4e89b8ec83d9fad39582292 Mon Sep 17 00:00:00 2001 From: Diego Nava <8563843+diego1q2w@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:34:23 +0200 Subject: [PATCH 11/66] fix validator state when trying to update the max-rate (#4647) Co-authored-by: Casey Gardiner <117784577+ONECasey@users.noreply.github.com> --- core/state/statedb.go | 5 ++++- internal/chain/engine.go | 4 ++-- internal/params/config.go | 14 ++++++++++++++ staking/availability/measure.go | 10 +++++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index fce6f750b5..d2351d51ac 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -895,7 +895,10 @@ func (db *DB) Finalise(deleteEmptyObjects bool) { // TODO: remove validator cache after commit for addr, wrapper := range db.stateValidators { if err := db.UpdateValidatorWrapper(addr, wrapper); err != nil { - utils.Logger().Warn().Err(err).Msg("Unable to update the validator wrapper on the finalize") + utils.Logger().Warn().Err(err). + Str("name", wrapper.Name). + Str("addr", addr.String()). + Msg("Unable to update the validator wrapper on the finalize") } } addressesToPrefetch := make([][]byte, 0, len(db.journal.dirties)) diff --git a/internal/chain/engine.go b/internal/chain/engine.go index d0e8e02db7..5bf8dc629d 100644 --- a/internal/chain/engine.go +++ b/internal/chain/engine.go @@ -458,7 +458,7 @@ func setElectionEpochAndMinFee(chain engine.ChainReader, header *block.Header, s if config.IsMaxRate(newShardState.Epoch) { for _, addr := range chain.ValidatorCandidates() { - if _, err := availability.UpdateMaxCommissionFee(state, addr, minRate); err != nil { + if _, err := availability.UpdateMaxCommissionFee(newShardState.Epoch, config, state, addr, minRate); err != nil { return err } } @@ -489,7 +489,7 @@ func setElectionEpochAndMinFee(chain engine.ChainReader, header *block.Header, s // higher than the the MaxRate by UpdateMinimumCommissionFee above if config.IsMaxRate(newShardState.Epoch) && minRateNotZero { for _, addr := range chain.ValidatorCandidates() { - if _, err := availability.UpdateMaxCommissionFee(state, addr, minRate); err != nil { + if _, err := availability.UpdateMaxCommissionFee(newShardState.Epoch, config, state, addr, minRate); err != nil { return err } } diff --git a/internal/params/config.go b/internal/params/config.go index 421ae3223c..e7548c3588 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -75,6 +75,7 @@ var ( ValidatorCodeFixEpoch: big.NewInt(1535), // 2023-07-20 05:51:07+00:00 HIP30Epoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00 BlockGas30MEpoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00 + TopMaxRateEpoch: EpochTBD, MaxRateEpoch: big.NewInt(1733), // 2023-12-17 12:20:15+00:00 DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, @@ -121,6 +122,7 @@ var ( ValidatorCodeFixEpoch: big.NewInt(1296), // 2023-04-28 07:14:20+00:00 HIP30Epoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00 BlockGas30MEpoch: big.NewInt(2176), // 2023-10-12 10:00:00+00:00 + TopMaxRateEpoch: EpochTBD, MaxRateEpoch: big.NewInt(2520), // 2023-12-16 12:17:14+00:00 DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: big.NewInt(3044), @@ -168,6 +170,7 @@ var ( HIP30Epoch: EpochTBD, BlockGas30MEpoch: big.NewInt(0), MaxRateEpoch: EpochTBD, + TopMaxRateEpoch: EpochTBD, DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, } @@ -261,6 +264,7 @@ var ( ValidatorCodeFixEpoch: EpochTBD, HIP30Epoch: EpochTBD, BlockGas30MEpoch: big.NewInt(0), + TopMaxRateEpoch: big.NewInt(0), MaxRateEpoch: EpochTBD, DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, @@ -308,6 +312,7 @@ var ( HIP30Epoch: EpochTBD, BlockGas30MEpoch: big.NewInt(0), MaxRateEpoch: EpochTBD, + TopMaxRateEpoch: EpochTBD, DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, } @@ -358,6 +363,7 @@ var ( big.NewInt(0), // MaxRateEpoch big.NewInt(0), // MaxRateEpoch big.NewInt(0), + big.NewInt(0), } // TestChainConfig ... @@ -405,6 +411,7 @@ var ( big.NewInt(0), // BlockGas30M big.NewInt(0), // MaxRateEpoch big.NewInt(0), // MaxRateEpoch + big.NewInt(0), // MaxRateEpoch big.NewInt(0), } @@ -578,6 +585,9 @@ type ChainConfig struct { // MaxRateEpoch will make sure the validator max-rate is at least equal to the minRate + the validator max-rate-increase MaxRateEpoch *big.Int `json:"max-rate-epoch,omitempty"` + + // TopMaxRateEpoch will make sure the validator max-rate is less to 100% for the cases where the minRate + the validator max-rate-increase > 100% + TopMaxRateEpoch *big.Int `json:"top-max-rate-epoch,omitempty"` } // String implements the fmt.Stringer interface. @@ -849,6 +859,10 @@ func (c *ChainConfig) IsMaxRate(epoch *big.Int) bool { return isForked(c.MaxRateEpoch, epoch) } +func (c *ChainConfig) IsTopMaxRate(epoch *big.Int) bool { + return isForked(c.TopMaxRateEpoch, epoch) +} + // During this epoch, shards 2 and 3 will start sending // their balances over to shard 0 or 1. func (c *ChainConfig) IsOneEpochBeforeHIP30(epoch *big.Int) bool { diff --git a/staking/availability/measure.go b/staking/availability/measure.go index 575c804380..faa105f261 100644 --- a/staking/availability/measure.go +++ b/staking/availability/measure.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/harmony-one/harmony/crypto/bls" + "github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/shard" @@ -267,7 +268,7 @@ func UpdateMinimumCommissionFee( } // UpdateMaxCommissionFee makes sure the max-rate is at least higher than the rate + max-rate-change. -func UpdateMaxCommissionFee(state *state.DB, addr common.Address, minRate numeric.Dec) (bool, error) { +func UpdateMaxCommissionFee(epoch *big.Int, config *params.ChainConfig, state *state.DB, addr common.Address, minRate numeric.Dec) (bool, error) { utils.Logger().Info().Msg("begin update max commission fee") wrapper, err := state.ValidatorWrapper(addr, true, false) @@ -277,6 +278,13 @@ func UpdateMaxCommissionFee(state *state.DB, addr common.Address, minRate numeri minMaxRate := minRate.Add(wrapper.MaxChangeRate) + if config.IsTopMaxRate(epoch) { + hundredPercent := numeric.NewDec(1) + if minMaxRate.GT(hundredPercent) { + minMaxRate = hundredPercent + } + } + if wrapper.MaxRate.LT(minMaxRate) { utils.Logger().Info(). Str("addr", addr.Hex()). From a3881d434d69fb35ee6e4e1b2752415347700ce9 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Thu, 2 May 2024 03:55:56 -0400 Subject: [PATCH 12/66] Improve staged stream sync (#4660) * disable stream sync for partner network and other networks * remove unused tx in block manager * add log for staged sync creation * change bucket for stroring progress in staged stream sync, fix saveBlocks tx issue * refactor stream sync db initialization * set SnapshotLimit to zero for localnet * add new logs for stream request manager --- api/service/stagedstreamsync/block_manager.go | 5 +- api/service/stagedstreamsync/stage_bodies.go | 52 ++++++++-------- api/service/stagedstreamsync/stages.go | 8 +-- api/service/stagedstreamsync/syncing.go | 61 +++++++++++-------- api/service/stagedsync/syncing.go | 18 ++++++ cmd/harmony/config.go | 1 + cmd/harmony/default.go | 8 +-- .../common/requestmanager/requestmanager.go | 5 +- 8 files changed, 94 insertions(+), 64 deletions(-) diff --git a/api/service/stagedstreamsync/block_manager.go b/api/service/stagedstreamsync/block_manager.go index d614d24205..d651dcab0e 100644 --- a/api/service/stagedstreamsync/block_manager.go +++ b/api/service/stagedstreamsync/block_manager.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/common" sttypes "github.com/harmony-one/harmony/p2p/stream/types" - "github.com/ledgerwatch/erigon-lib/kv" "github.com/rs/zerolog" ) @@ -19,7 +18,6 @@ type BlockDownloadDetails struct { // blockDownloadManager is the helper structure for get blocks request management type blockDownloadManager struct { chain blockChain - tx kv.RwTx targetBN uint64 requesting map[uint64]struct{} // block numbers that have been assigned to workers but not received @@ -32,10 +30,9 @@ type blockDownloadManager struct { lock sync.Mutex } -func newBlockDownloadManager(tx kv.RwTx, chain blockChain, targetBN uint64, logger zerolog.Logger) *blockDownloadManager { +func newBlockDownloadManager(chain blockChain, targetBN uint64, logger zerolog.Logger) *blockDownloadManager { return &blockDownloadManager{ chain: chain, - tx: tx, targetBN: targetBN, requesting: make(map[uint64]struct{}), processing: make(map[uint64]struct{}), diff --git a/api/service/stagedstreamsync/stage_bodies.go b/api/service/stagedstreamsync/stage_bodies.go index 9fdf4681a1..18cbb1722a 100644 --- a/api/service/stagedstreamsync/stage_bodies.go +++ b/api/service/stagedstreamsync/stage_bodies.go @@ -77,6 +77,15 @@ func (b *StageBodies) Exec(ctx context.Context, firstCycle bool, invalidBlockRev currProgress := uint64(0) targetHeight := s.state.currentCycle.TargetHeight + if useInternalTx { + var err error + tx, err = b.configs.db.BeginRw(ctx) + if err != nil { + return err + } + defer tx.Rollback() + } + if errV := CreateView(ctx, b.configs.db, tx, func(etx kv.Tx) error { if currProgress, err = s.CurrentStageProgress(etx); err != nil { return err @@ -97,24 +106,14 @@ func (b *StageBodies) Exec(ctx context.Context, firstCycle bool, invalidBlockRev return nil } - // size := uint64(0) startTime := time.Now() // startBlock := currProgress if b.configs.logProgress { fmt.Print("\033[s") // save the cursor position } - if useInternalTx { - var err error - tx, err = b.configs.db.BeginRw(ctx) - if err != nil { - return err - } - defer tx.Rollback() - } - // Fetch blocks from neighbors - s.state.gbm = newBlockDownloadManager(tx, b.configs.bc, targetHeight, s.state.logger) + s.state.gbm = newBlockDownloadManager(b.configs.bc, targetHeight, s.state.logger) // Setup workers to fetch blocks from remote node var wg sync.WaitGroup @@ -188,7 +187,7 @@ func (b *StageBodies) runBlockWorkerLoop(ctx context.Context, gbm *blockDownload gbm.HandleRequestError(batch, err, stid) b.configs.protocol.RemoveStream(stid) } else { - if err = b.saveBlocks(ctx, gbm.tx, batch, blockBytes, sigBytes, loopID, stid); err != nil { + if err = b.saveBlocks(ctx, nil, batch, blockBytes, sigBytes, loopID, stid); err != nil { panic(ErrSaveBlocksToDbFailed) } gbm.HandleRequestResult(batch, blockBytes, sigBytes, loopID, stid) @@ -239,8 +238,9 @@ func (b *StageBodies) verifyBlockAndExtractReceiptsData(batchBlockBytes [][]byte // redownloadBadBlock tries to redownload the bad block from other streams func (b *StageBodies) redownloadBadBlock(ctx context.Context, s *StageState) error { - batch := make([]uint64, 1) - batch = append(batch, s.state.invalidBlock.Number) + batch := []uint64{s.state.invalidBlock.Number} + +badBlockDownloadLoop: for { if b.configs.protocol.NumStreams() == 0 { @@ -253,21 +253,20 @@ func (b *StageBodies) redownloadBadBlock(ctx context.Context, s *StageState) err } continue } - isOneOfTheBadStreams := false for _, id := range s.state.invalidBlock.StreamID { if id == stid { + // TODO: if block is invalid then call StreamFailed b.configs.protocol.StreamFailed(stid, "re-download bad block from this stream failed") - isOneOfTheBadStreams = true - break + continue badBlockDownloadLoop } } - if isOneOfTheBadStreams { - continue - } s.state.gbm.SetDownloadDetails(batch, 0, stid) if errU := b.configs.blockDBs[0].Update(ctx, func(tx kv.RwTx) error { if err = b.saveBlocks(ctx, tx, batch, blockBytes, sigBytes, 0, stid); err != nil { - return errors.Errorf("[STAGED_STREAM_SYNC] saving re-downloaded bad block to db failed.") + utils.Logger().Error(). + Err(err). + Msg("[STAGED_STREAM_SYNC] saving re-downloaded bad block to db failed") + return errors.Errorf("%s: %s", ErrSaveBlocksToDbFailed.Error(), err.Error()) } return nil }); errU != nil { @@ -314,11 +313,14 @@ func validateGetBlocksResult(requested []uint64, result []*types.Block) error { // saveBlocks saves the blocks into db func (b *StageBodies) saveBlocks(ctx context.Context, tx kv.RwTx, bns []uint64, blockBytes [][]byte, sigBytes [][]byte, loopID int, stid sttypes.StreamID) error { - tx, err := b.configs.blockDBs[loopID].BeginRw(ctx) - if err != nil { - return err + if tx == nil { + var err error + tx, err = b.configs.blockDBs[loopID].BeginRw(ctx) + if err != nil { + return err + } + defer tx.Rollback() } - defer tx.Rollback() for i := uint64(0); i < uint64(len(blockBytes)); i++ { block := blockBytes[i] diff --git a/api/service/stagedstreamsync/stages.go b/api/service/stagedstreamsync/stages.go index 33f3b293b0..03dcafea3c 100644 --- a/api/service/stagedstreamsync/stages.go +++ b/api/service/stagedstreamsync/stages.go @@ -40,7 +40,7 @@ func GetStageID(stage SyncStageID, isBeacon bool, prune bool) []byte { // GetStageProgress retrieves saved progress of a given sync stage from the database func GetStageProgress(db kv.Getter, stage SyncStageID, isBeacon bool) (uint64, error) { stgID := GetStageID(stage, isBeacon, false) - v, err := db.GetOne(kv.SyncStageProgress, stgID) + v, err := db.GetOne(StageProgressBucket, stgID) if err != nil { return 0, err } @@ -50,13 +50,13 @@ func GetStageProgress(db kv.Getter, stage SyncStageID, isBeacon bool) (uint64, e // SaveStageProgress saves progress of given sync stage func SaveStageProgress(db kv.Putter, stage SyncStageID, isBeacon bool, progress uint64) error { stgID := GetStageID(stage, isBeacon, false) - return db.Put(kv.SyncStageProgress, stgID, marshalData(progress)) + return db.Put(StageProgressBucket, stgID, marshalData(progress)) } // GetStageCleanUpProgress retrieves saved progress of given sync stage from the database func GetStageCleanUpProgress(db kv.Getter, stage SyncStageID, isBeacon bool) (uint64, error) { stgID := GetStageID(stage, isBeacon, true) - v, err := db.GetOne(kv.SyncStageProgress, stgID) + v, err := db.GetOne(StageProgressBucket, stgID) if err != nil { return 0, err } @@ -66,5 +66,5 @@ func GetStageCleanUpProgress(db kv.Getter, stage SyncStageID, isBeacon bool) (ui // SaveStageCleanUpProgress stores the progress of the clean up for a given sync stage to the database func SaveStageCleanUpProgress(db kv.Putter, stage SyncStageID, isBeacon bool, progress uint64) error { stgID := GetStageID(stage, isBeacon, true) - return db.Put(kv.SyncStageProgress, stgID, marshalData(progress)) + return db.Put(StageProgressBucket, stgID, marshalData(progress)) } diff --git a/api/service/stagedstreamsync/syncing.go b/api/service/stagedstreamsync/syncing.go index 0db0dd4e2d..b996b516a8 100644 --- a/api/service/stagedstreamsync/syncing.go +++ b/api/service/stagedstreamsync/syncing.go @@ -17,7 +17,6 @@ import ( sttypes "github.com/harmony-one/harmony/p2p/stream/types" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/mdbx" - "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/log/v3" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -62,23 +61,34 @@ func CreateStagedSync(ctx context.Context, var mainDB kv.RwDB dbs := make([]kv.RwDB, config.Concurrency) if config.UseMemDB { - mainDB = memdb.New(getBlockDbPath(bc.ShardID(), isBeaconNode, -1, dbDir)) + mdbPath := getBlockDbPath(bc.ShardID(), isBeaconNode, -1, dbDir) + logger.Info(). + Str("path", mdbPath). + Msg(WrapStagedSyncMsg("creating main db in memory")) + mainDB = mdbx.NewMDBX(log.New()).InMem(mdbPath).MustOpen() for i := 0; i < config.Concurrency; i++ { dbPath := getBlockDbPath(bc.ShardID(), isBeaconNode, i, dbDir) - dbs[i] = memdb.New(dbPath) + logger.Info(). + Str("path", dbPath). + Msg(WrapStagedSyncMsg("creating blocks db in memory")) + dbs[i] = mdbx.NewMDBX(log.New()).InMem(dbPath).MustOpen() } } else { + mdbPath := getBlockDbPath(bc.ShardID(), isBeaconNode, -1, dbDir) logger.Info(). - Str("path", getBlockDbPath(bc.ShardID(), isBeaconNode, -1, dbDir)). - Msg(WrapStagedSyncMsg("creating main db")) - mainDB = mdbx.NewMDBX(log.New()).Path(getBlockDbPath(bc.ShardID(), isBeaconNode, -1, dbDir)).MustOpen() + Str("path", mdbPath). + Msg(WrapStagedSyncMsg("creating main db in disk")) + mainDB = mdbx.NewMDBX(log.New()).Path(mdbPath).MustOpen() for i := 0; i < config.Concurrency; i++ { dbPath := getBlockDbPath(bc.ShardID(), isBeaconNode, i, dbDir) + logger.Info(). + Str("path", dbPath). + Msg(WrapStagedSyncMsg("creating blocks db in disk")) dbs[i] = mdbx.NewMDBX(log.New()).Path(dbPath).MustOpen() } } - if errInitDB := initDB(ctx, mainDB, dbs, config.Concurrency); errInitDB != nil { + if errInitDB := initDB(ctx, mainDB, dbs); errInitDB != nil { logger.Error().Err(errInitDB).Msg("create staged sync instance failed") return nil, errInitDB } @@ -118,7 +128,8 @@ func CreateStagedSync(ctx context.Context, Str("dbDir", dbDir). Bool("serverOnly", config.ServerOnly). Int("minStreams", config.MinStreams). - Msg(WrapStagedSyncMsg("staged sync created successfully")) + Str("dbDir", dbDir). + Msg(WrapStagedSyncMsg("staged stream sync created successfully")) return New( bc, @@ -134,7 +145,7 @@ func CreateStagedSync(ctx context.Context, } // initDB inits the sync loop main database and create buckets -func initDB(ctx context.Context, mainDB kv.RwDB, dbs []kv.RwDB, concurrency int) error { +func initDB(ctx context.Context, mainDB kv.RwDB, dbs []kv.RwDB) error { // create buckets for mainDB tx, errRW := mainDB.BeginRw(ctx) @@ -143,8 +154,8 @@ func initDB(ctx context.Context, mainDB kv.RwDB, dbs []kv.RwDB, concurrency int) } defer tx.Rollback() - for _, name := range Buckets { - if err := tx.CreateBucket(GetStageName(name, false, false)); err != nil { + for _, bucketName := range Buckets { + if err := tx.CreateBucket(bucketName); err != nil { return err } } @@ -152,34 +163,32 @@ func initDB(ctx context.Context, mainDB kv.RwDB, dbs []kv.RwDB, concurrency int) return err } - // create buckets for block cache DBs - for _, db := range dbs { - tx, errRW := db.BeginRw(ctx) - if errRW != nil { - return errRW + createBlockBuckets := func(db kv.RwDB) error { + tx, err := db.BeginRw(ctx) + if err != nil { + return err } - + defer tx.Rollback() if err := tx.CreateBucket(BlocksBucket); err != nil { return err } if err := tx.CreateBucket(BlockSignaturesBucket); err != nil { return err } - if err := tx.Commit(); err != nil { return err } + return nil } - return nil -} - -// getMemDbTempPath returns the path of the temporary cache database for memdb -func getMemDbTempPath(dbDir string, dbIndex int) string { - if dbIndex >= 0 { - return fmt.Sprintf("%s_%d", filepath.Join(dbDir, "cache/memdb/db"), dbIndex) + // create buckets for block cache DBs + for _, db := range dbs { + if err := createBlockBuckets(db); err != nil { + return err + } } - return filepath.Join(dbDir, "cache/memdb/db_main") + + return nil } // getBlockDbPath returns the path of the cache database which stores blocks diff --git a/api/service/stagedsync/syncing.go b/api/service/stagedsync/syncing.go index 623ea476d9..980269d8c8 100644 --- a/api/service/stagedsync/syncing.go +++ b/api/service/stagedsync/syncing.go @@ -112,6 +112,24 @@ func CreateStagedSync( finishCfg, ) + utils.Logger().Info(). + Str("ip", ip). + Str("port", port). + Uint32("shard", bc.ShardID()). + Bool("isExplorer", isExplorer). + Bool("TurboMode", TurboMode). + Bool("memdb", UseMemDB). + Bool("doubleCheckBlockHashes", doubleCheckBlockHashes). + Uint64("maxBlocksPerCycle", maxBlocksPerCycle). + Uint64("maxBackgroundBlocks", maxBackgroundBlocks). + Uint64("maxMemSyncCycleSize", maxMemSyncCycleSize). + Bool("verifyAllSig", verifyAllSig). + Uint64("verifyHeaderBatchSize", verifyHeaderBatchSize). + Int("insertChainBatchSize", insertChainBatchSize). + Bool("debugMode", debugMode). + Str("dbDir", dbDir). + Msg("[STAGED_SYNC] staged sync created successfully") + return New(ctx, ip, port, diff --git a/cmd/harmony/config.go b/cmd/harmony/config.go index 0b798551ae..0d2632d8aa 100644 --- a/cmd/harmony/config.go +++ b/cmd/harmony/config.go @@ -173,6 +173,7 @@ func getDefaultCacheConfig(nt nodeconfig.NetworkType) harmonyconfig.CacheConfig case nodeconfig.Localnet: cacheConfig.Disabled = false cacheConfig.Preimages = false + cacheConfig.SnapshotLimit = 0 default: cacheConfig.Disabled = false cacheConfig.Preimages = true diff --git a/cmd/harmony/default.go b/cmd/harmony/default.go index 22b964b997..217c7306f1 100644 --- a/cmd/harmony/default.go +++ b/cmd/harmony/default.go @@ -241,9 +241,9 @@ var ( } defaultPartnerSyncConfig = harmonyconfig.SyncConfig{ - Enabled: true, + Enabled: false, SyncMode: 0, - Downloader: true, + Downloader: false, StagedSync: false, StagedSyncCfg: defaultStagedSyncConfig, Concurrency: 2, @@ -257,9 +257,9 @@ var ( } defaultElseSyncConfig = harmonyconfig.SyncConfig{ - Enabled: true, + Enabled: false, SyncMode: 0, - Downloader: true, + Downloader: false, StagedSync: false, StagedSyncCfg: defaultStagedSyncConfig, Concurrency: 4, diff --git a/p2p/stream/common/requestmanager/requestmanager.go b/p2p/stream/common/requestmanager/requestmanager.go index 37a810dcc3..84d7210c7a 100644 --- a/p2p/stream/common/requestmanager/requestmanager.go +++ b/p2p/stream/common/requestmanager/requestmanager.go @@ -154,6 +154,8 @@ func (rm *requestManager) loop() { if req == nil { break loop } + rm.logger.Debug().Str("request", req.String()). + Msg("add new incoming request to pending queue") rm.addPendingRequest(req, st) b, err := req.Encode() if err != nil { @@ -202,7 +204,8 @@ func (rm *requestManager) loop() { func (rm *requestManager) handleNewRequest(req *request) bool { rm.lock.Lock() defer rm.lock.Unlock() - + rm.logger.Debug().Str("request", req.String()). + Msg("add new outgoing request to waiting queue") err := rm.addRequestToWaitings(req, reqPriorityLow) if err != nil { rm.logger.Warn().Err(err).Msg("failed to add new request to waitings") From 1375a3b6c0a1569453368a1186bb7682d08d0a9c Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 9 May 2024 10:37:43 -0400 Subject: [PATCH 13/66] pprof for bootnode (#4664) --- cmd/bootnode/main.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 92d6674b94..538b53e569 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -5,15 +5,16 @@ package main import ( "flag" "fmt" + "net/http" + _ "net/http/pprof" "os" "path" "github.com/ethereum/go-ethereum/log" - net "github.com/libp2p/go-libp2p/core/network" - ma "github.com/multiformats/go-multiaddr" - "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/p2p" + net "github.com/libp2p/go-libp2p/core/network" + ma "github.com/multiformats/go-multiaddr" ) // ConnLogger .. @@ -104,6 +105,12 @@ func main() { maxConnPerIP := flag.Int("max_conn_per_ip", 10, "max connections number for same ip") forceReachabilityPublic := flag.Bool("force_public", false, "forcing the local node to believe it is reachable externally") + pprof := flag.Bool("pprof", false, "enabled pprof") + pprofAddr := flag.String("pprof.addr", "127.0.0.1:6060", "http pprof address") + //keyFile := flag.String("pprof.profile.names", "", "the private key file of the bootnode") + //keyFile := flag.String("pprof.profile.intervals", "600", "the private key file of the bootnode") + //keyFile := flag.String("pprof.profile.intervals", "", "the private key file of the bootnode") + flag.Parse() if *versionFlag { @@ -148,5 +155,10 @@ func main() { host.GetP2PHost().Network().Notify(NewConnLogger(utils.GetLogInstance())) } + if *pprof { + fmt.Printf("starting pprof on http://%s/debug/pprof/\n", *pprofAddr) + http.ListenAndServe(*pprofAddr, nil) + } + select {} } From 5a33e2ac11ec49ef39612f233040cd997764454b Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Tue, 14 May 2024 03:16:52 -0400 Subject: [PATCH 14/66] improve logs to reduce OUT of SYNC info logs (#4667) --- api/service/legacysync/epoch_syncing.go | 28 ++++++++++++++------ api/service/legacysync/syncing.go | 34 +++++++++++++++++-------- api/service/stagedsync/stagedsync.go | 5 +++- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/api/service/legacysync/epoch_syncing.go b/api/service/legacysync/epoch_syncing.go index 7719c8a819..09c4a62da8 100644 --- a/api/service/legacysync/epoch_syncing.go +++ b/api/service/legacysync/epoch_syncing.go @@ -101,13 +101,25 @@ func syncLoop(bc core.BlockChain, syncConfig *SyncConfig) (timeout int) { return 10 } + utils.Logger().Info(). + Bool("isBeacon", isBeacon). + Uint32("ShardID", bc.ShardID()). + Uint64("otherEpoch", shard.Schedule.CalcEpochNumber(maxHeight).Uint64()). + Uint64("currentEpoch", bc.CurrentBlock().Epoch().Uint64()). + Int("peers count", syncConfig.PeersCount()). + Msg("[EPOCHSYNC] Node is OUT OF SYNC, it's trying to get fully synchronized") + for { curEpoch := bc.CurrentBlock().Epoch().Uint64() otherEpoch := shard.Schedule.CalcEpochNumber(maxHeight).Uint64() if otherEpoch == curEpoch+1 { utils.Logger().Info(). - Msgf("[EPOCHSYNC] Node is now IN SYNC! (isBeacon: %t, ShardID: %d, otherEpoch: %d, currentEpoch: %d, peersCount: %d)", - isBeacon, bc.ShardID(), otherEpoch, curEpoch, syncConfig.PeersCount()) + Bool("isBeacon", isBeacon). + Uint32("ShardID", bc.ShardID()). + Uint64("otherEpoch", otherEpoch). + Uint64("currentEpoch", curEpoch). + Int("peers count", syncConfig.PeersCount()). + Msg("[EPOCHSYNC] Node is now IN SYNC!") return 60 } if otherEpoch < curEpoch { @@ -117,10 +129,6 @@ func syncLoop(bc core.BlockChain, syncConfig *SyncConfig) (timeout int) { return 2 } - utils.Logger().Info(). - Msgf("[EPOCHSYNC] Node is OUT OF SYNC (isBeacon: %t, ShardID: %d, otherEpoch: %d, currentEpoch: %d, peers count %d)", - isBeacon, bc.ShardID(), otherEpoch, curEpoch, syncConfig.PeersCount()) - var heights []uint64 loopEpoch := curEpoch + 1 for len(heights) < int(SyncLoopBatchSize) { @@ -142,8 +150,12 @@ func syncLoop(bc core.BlockChain, syncConfig *SyncConfig) (timeout int) { return 10 } utils.Logger().Error().Err(err). - Msgf("[EPOCHSYNC] ProcessStateSync failed (isBeacon: %t, ShardID: %d, otherEpoch: %d, currentEpoch: %d)", - isBeacon, bc.ShardID(), otherEpoch, curEpoch) + Bool("isBeacon", isBeacon). + Uint32("ShardID", bc.ShardID()). + Uint64("otherEpoch", otherEpoch). + Uint64("currentEpoch", curEpoch). + Int("peers count", syncConfig.PeersCount()). + Msg("[EPOCHSYNC] ProcessStateSync failed") return 2 } } diff --git a/api/service/legacysync/syncing.go b/api/service/legacysync/syncing.go index a85a5e9d51..e65ef48742 100644 --- a/api/service/legacysync/syncing.go +++ b/api/service/legacysync/syncing.go @@ -1093,29 +1093,35 @@ func (ss *StateSync) SyncLoop(bc core.BlockChain, isBeacon bool, consensus *cons ss.RegisterNodeInfo() } + utils.Logger().Info(). + Bool("isBeacon", isBeacon). + Uint32("ShardID", bc.ShardID()). + Uint64("currentHeight", bc.CurrentBlock().NumberU64()). + Int("peers count", ss.syncConfig.PeersCount()). + Msg("[SYNC] Node is OUT OF SYNC, it's trying to get fully synchronized") + for { start := time.Now() currentHeight := bc.CurrentBlock().NumberU64() otherHeight, errMaxHeight := getMaxPeerHeight(ss.syncConfig) if errMaxHeight != nil { - utils.Logger().Error(). + utils.Logger().Error().Err(errMaxHeight). Bool("isBeacon", isBeacon). Uint32("ShardID", bc.ShardID()). Uint64("currentHeight", currentHeight). Int("peers count", ss.syncConfig.PeersCount()). - Msgf("[SYNC] get max height failed") + Msg("[SYNC] get max height failed") break } if currentHeight >= otherHeight { utils.Logger().Info(). - Msgf("[SYNC] Node is now IN SYNC! (isBeacon: %t, ShardID: %d, otherHeight: %d, currentHeight: %d)", - isBeacon, bc.ShardID(), otherHeight, currentHeight) + Bool("isBeacon", isBeacon). + Uint32("ShardID", bc.ShardID()). + Uint64("currentHeight", bc.CurrentBlock().NumberU64()). + Int("peers count", ss.syncConfig.PeersCount()). + Msg("[SYNC] Node is now IN SYNC!") break } - utils.Logger().Info(). - Msgf("[SYNC] Node is OUT OF SYNC (isBeacon: %t, ShardID: %d, otherHeight: %d, currentHeight: %d)", - isBeacon, bc.ShardID(), otherHeight, currentHeight) - startHash := bc.CurrentBlock().Hash() size := uint32(otherHeight - currentHeight) if size > SyncLoopBatchSize { @@ -1127,8 +1133,11 @@ func (ss *StateSync) SyncLoop(bc core.BlockChain, isBeacon bool, consensus *cons continue } utils.Logger().Error().Err(err). - Msgf("[SYNC] ProcessStateSync failed (isBeacon: %t, ShardID: %d, otherHeight: %d, currentHeight: %d)", - isBeacon, bc.ShardID(), otherHeight, currentHeight) + Bool("isBeacon", isBeacon). + Uint32("ShardID", bc.ShardID()). + Uint64("currentHeight", bc.CurrentBlock().NumberU64()). + Int("peers count", ss.syncConfig.PeersCount()). + Msg("[SYNC] ProcessStateSync failed") ss.purgeOldBlocksFromCache() break } @@ -1332,6 +1341,8 @@ func (ss *StateSync) isSynchronized(doubleCheck bool) SyncCheckResult { utils.Logger().Info(). Uint64("OtherHeight", otherHeight1). Uint64("lastHeight", lastHeight). + Uint64("heightDiff", heightDiff). + Bool("wasOutOfSync", wasOutOfSync). Msg("[SYNC] Checking sync status") return SyncCheckResult{ IsSynchronized: !wasOutOfSync, @@ -1354,7 +1365,8 @@ func (ss *StateSync) isSynchronized(doubleCheck bool) SyncCheckResult { Uint64("OtherHeight2", otherHeight2). Uint64("lastHeight", lastHeight). Uint64("currentHeight", currentHeight). - Msg("[SYNC] Checking sync status") + Bool("isOutOfSync", isOutOfSync). + Msg("[SYNC] Double checking sync status") // Only confirm out of sync when the node has lower height and didn't move in heights for 2 consecutive checks heightDiff := otherHeight2 - lastHeight if otherHeight2 < lastHeight { diff --git a/api/service/stagedsync/stagedsync.go b/api/service/stagedsync/stagedsync.go index 7959a05d29..53f56a375e 100644 --- a/api/service/stagedsync/stagedsync.go +++ b/api/service/stagedsync/stagedsync.go @@ -1306,6 +1306,8 @@ func (ss *StagedSync) isSynchronized(doubleCheck bool) SyncCheckResult { utils.Logger().Info(). Uint64("OtherHeight", otherHeight1). Uint64("lastHeight", lastHeight). + Uint64("heightDiff", heightDiff). + Bool("wasOutOfSync", wasOutOfSync). Msg("[STAGED_SYNC] Checking sync status") return SyncCheckResult{ IsSynchronized: !wasOutOfSync, @@ -1328,7 +1330,8 @@ func (ss *StagedSync) isSynchronized(doubleCheck bool) SyncCheckResult { Uint64("OtherHeight2", otherHeight2). Uint64("lastHeight", lastHeight). Uint64("currentHeight", currentHeight). - Msg("[STAGED_SYNC] Checking sync status") + Bool("isOutOfSync", isOutOfSync). + Msg("[STAGED_SYNC] Double checking sync status") // Only confirm out of sync when the node has lower height and didn't move in heights for 2 consecutive checks heightDiff := otherHeight2 - lastHeight if otherHeight2 < lastHeight { From b526c3a4ef80ce97f2b165343652bb90634c5bdd Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Sat, 20 Apr 2024 21:40:46 -0400 Subject: [PATCH 15/66] Force sync when view change and received message with higher height. --- consensus/validator.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/consensus/validator.go b/consensus/validator.go index 14f4b52167..d76ef34b84 100644 --- a/consensus/validator.go +++ b/consensus/validator.go @@ -29,6 +29,15 @@ func (consensus *Consensus) onAnnounce(msg *msg_pb.Message) { // NOTE let it handle its own logs if !consensus.onAnnounceSanityChecks(recvMsg) { + if consensus.isViewChangingMode() && recvMsg.BlockNum > consensus.BlockNum() { + consensus.getLogger().Info(). + Uint64("myBlockNum", consensus.BlockNum()). + Uint64("MsgBlockNum", recvMsg.BlockNum). + Hex("myBlockHash", consensus.blockHash[:]). + Hex("MsgBlockHash", recvMsg.BlockHash[:]). + Msg("[OnCommitted] low consensus block number. Spin up state sync") + consensus.spinUpStateSync() + } return } consensus.StartFinalityCount() From 2ece5a64d9785ac36af2a3682322c7f53302d217 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Tue, 21 May 2024 00:32:52 -0400 Subject: [PATCH 16/66] Removed unused method `NthNextHmyExt` (#4670) --- consensus/quorum/quorom_test.go | 46 ----------------------- consensus/quorum/quorum.go | 49 +------------------------ consensus/quorum/thread_safe_decider.go | 6 --- 3 files changed, 2 insertions(+), 99 deletions(-) diff --git a/consensus/quorum/quorom_test.go b/consensus/quorum/quorom_test.go index 0b5c265b14..67f9496b17 100644 --- a/consensus/quorum/quorom_test.go +++ b/consensus/quorum/quorom_test.go @@ -8,7 +8,6 @@ import ( bls_core "github.com/harmony-one/bls/ffi/go/bls" harmony_bls "github.com/harmony-one/harmony/crypto/bls" shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding" - "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/shard" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -550,51 +549,6 @@ func TestInvalidAggregateSig(test *testing.T) { } } -func TestNthNextHmyExt(test *testing.T) { - numHmyNodes := 10 - numAllExtNodes := 10 - numAllowlistExtNodes := numAllExtNodes / 2 - allowlist := shardingconfig.Allowlist{MaxLimitPerShard: numAllowlistExtNodes - 1} - blsKeys := []harmony_bls.PublicKeyWrapper{} - for i := 0; i < numHmyNodes+numAllExtNodes; i++ { - blsKey := harmony_bls.RandPrivateKey() - wrapper := harmony_bls.PublicKeyWrapper{Object: blsKey.GetPublicKey()} - wrapper.Bytes.FromLibBLSPublicKey(wrapper.Object) - blsKeys = append(blsKeys, wrapper) - } - allowlistLeaders := blsKeys[len(blsKeys)-allowlist.MaxLimitPerShard:] - allLeaders := append(blsKeys[:numHmyNodes], allowlistLeaders...) - - decider := NewDecider(SuperMajorityVote, shard.BeaconChainShardID) - fakeInstance := shardingconfig.MustNewInstance(2, 20, numHmyNodes, 0, numeric.OneDec(), nil, nil, allowlist, nil, numeric.ZeroDec(), common.Address{}, nil, 0) - - decider.UpdateParticipants(blsKeys, allowlistLeaders) - for i := 0; i < len(allLeaders); i++ { - leader := allLeaders[i] - for j := 0; j < len(allLeaders)*2; j++ { - expectNextLeader := allLeaders[(i+j)%len(allLeaders)] - found, nextLeader := decider.NthNextHmyExt(fakeInstance, &leader, j) - if !found { - test.Fatal("next leader not found") - } - if expectNextLeader.Bytes != nextLeader.Bytes { - test.Fatal("next leader is not expected") - } - - preJ := -j - preIndex := (i + len(allLeaders) + preJ%len(allLeaders)) % len(allLeaders) - expectPreLeader := allLeaders[preIndex] - found, preLeader := decider.NthNextHmyExt(fakeInstance, &leader, preJ) - if !found { - test.Fatal("previous leader not found") - } - if expectPreLeader.Bytes != preLeader.Bytes { - test.Fatal("previous leader is not expected") - } - } - } -} - func TestCIdentities_NthNextValidatorHmy(t *testing.T) { address := []common.Address{ common.HexToAddress("0x1"), diff --git a/consensus/quorum/quorum.go b/consensus/quorum/quorum.go index 3930abef12..148c8cb4a9 100644 --- a/consensus/quorum/quorum.go +++ b/consensus/quorum/quorum.go @@ -3,7 +3,6 @@ package quorum import ( "fmt" "math/big" - "sort" "github.com/harmony-one/harmony/crypto/bls" @@ -78,7 +77,6 @@ type ParticipantTracker interface { // NthNextValidator returns key for next validator. It assumes external validators and leader rotation. NthNextValidator(slotList shard.SlotList, pubKey *bls.PublicKeyWrapper, next int) (bool, *bls.PublicKeyWrapper) NthNextHmy(instance shardingconfig.Instance, pubkey *bls.PublicKeyWrapper, next int) (bool, *bls.PublicKeyWrapper) - NthNextHmyExt(shardingconfig.Instance, *bls.PublicKeyWrapper, int) (bool, *bls.PublicKeyWrapper) FirstParticipant(shardingconfig.Instance) *bls.PublicKeyWrapper UpdateParticipants(pubKeys, allowlist []bls.PublicKeyWrapper) } @@ -151,10 +149,8 @@ type cIdentities struct { // Public keys of the committee including leader and validators publicKeys []bls.PublicKeyWrapper keyIndexMap map[bls.SerializedPublicKey]int - // every element is a index of publickKeys - allowlistIndex []int - prepare *votepower.Round - commit *votepower.Round + prepare *votepower.Round + commit *votepower.Round // viewIDSigs: every validator // sign on |viewID|blockHash| in view changing message viewChange *votepower.Round @@ -274,41 +270,6 @@ func (s *cIdentities) NthNextHmy(instance shardingconfig.Instance, pubKey *bls.P return found, &s.publicKeys[idx] } -// NthNextHmyExt return the Nth next pubkey of Harmony + allowlist nodes, next can be negative number -func (s *cIdentities) NthNextHmyExt(instance shardingconfig.Instance, pubKey *bls.PublicKeyWrapper, next int) (bool, *bls.PublicKeyWrapper) { - found := false - - idx := s.IndexOf(pubKey.Bytes) - if idx != -1 { - found = true - } - numHmyNodes := instance.NumHarmonyOperatedNodesPerShard() - // sanity check to avoid out of bound access - if numHmyNodes <= 0 || numHmyNodes > len(s.publicKeys) { - numHmyNodes = len(s.publicKeys) - } - nth := idx - if idx >= numHmyNodes { - nth = sort.SearchInts(s.allowlistIndex, idx) + numHmyNodes - } - - numExtNodes := instance.ExternalAllowlistLimit() - if numExtNodes > len(s.allowlistIndex) { - numExtNodes = len(s.allowlistIndex) - } - - totalNodes := numHmyNodes + numExtNodes - // (totalNodes + next%totalNodes) can convert negitive 'next' to positive - nth = (nth + totalNodes + next%totalNodes) % totalNodes - if nth < numHmyNodes { - idx = nth - } else { - // find index of external slot key - idx = s.allowlistIndex[nth-numHmyNodes] - } - return found, &s.publicKeys[idx] -} - // FirstParticipant returns the first participant of the shard func (s *cIdentities) FirstParticipant(instance shardingconfig.Instance) *bls.PublicKeyWrapper { return &s.publicKeys[0] @@ -323,12 +284,6 @@ func (s *cIdentities) UpdateParticipants(pubKeys, allowlist []bls.PublicKeyWrapp for i := range pubKeys { keyIndexMap[pubKeys[i].Bytes] = i } - for _, key := range allowlist { - if i, exist := keyIndexMap[key.Bytes]; exist { - s.allowlistIndex = append(s.allowlistIndex, i) - } - } - sort.Ints(s.allowlistIndex) s.publicKeys = pubKeys s.keyIndexMap = keyIndexMap } diff --git a/consensus/quorum/thread_safe_decider.go b/consensus/quorum/thread_safe_decider.go index 9999325f67..9df0ec03f1 100644 --- a/consensus/quorum/thread_safe_decider.go +++ b/consensus/quorum/thread_safe_decider.go @@ -64,12 +64,6 @@ func (a threadSafeDeciderImpl) NthNextHmy(instance shardingconfig.Instance, pubk return a.decider.NthNextHmy(instance, pubkey, next) } -func (a threadSafeDeciderImpl) NthNextHmyExt(instance shardingconfig.Instance, wrapper *bls.PublicKeyWrapper, i int) (bool, *bls.PublicKeyWrapper) { - a.mu.Lock() - defer a.mu.Unlock() - return a.decider.NthNextHmyExt(instance, wrapper, i) -} - func (a threadSafeDeciderImpl) FirstParticipant(instance shardingconfig.Instance) *bls.PublicKeyWrapper { a.mu.Lock() defer a.mu.Unlock() From 3dad8250f28b42b58a8094589ac1819fed1e8c58 Mon Sep 17 00:00:00 2001 From: guangwu Date: Wed, 22 May 2024 00:47:26 +0800 Subject: [PATCH 17/66] fix: close file (#4672) --- core/preimages.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/preimages.go b/core/preimages.go index 5034cc0e95..fff6364664 100644 --- a/core/preimages.go +++ b/core/preimages.go @@ -26,6 +26,7 @@ func ImportPreimages(chain BlockChain, path string) error { if err != nil { return fmt.Errorf("could not open file for reading: %s", err) } + defer reader.Close() csvReader := csv.NewReader(reader) dbReader := chain.ChainDb() imported := uint64(0) From 3d2959695a219a3584d4076027e42edd1c1019f3 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Thu, 23 May 2024 23:59:48 -0400 Subject: [PATCH 18/66] fix boot node instability issue, refactor p2p host configurations and add new features to p2p (#4676) --- cmd/bootnode/main.go | 13 ++ cmd/harmony/config_migrations.go | 23 +++ cmd/harmony/default.go | 8 +- cmd/harmony/flags.go | 50 +++++++ cmd/harmony/flags_test.go | 174 ++++++++++++++++++++++ cmd/harmony/main.go | 6 + go.mod | 1 + go.sum | 3 + internal/configs/harmony/harmony.go | 12 ++ internal/configs/node/network.go | 14 ++ p2p/host.go | 220 ++++++++++++++++++++-------- 11 files changed, 458 insertions(+), 66 deletions(-) diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 538b53e569..1802f478a8 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -9,6 +9,7 @@ import ( _ "net/http/pprof" "os" "path" + "time" "github.com/ethereum/go-ethereum/log" "github.com/harmony-one/harmony/internal/utils" @@ -91,6 +92,9 @@ func printVersion(me string) { } func main() { + timestamp := time.Now().Format("20060102150405") + defUserAgent := fmt.Sprintf("bootnode-%s", timestamp) + ip := flag.String("ip", "127.0.0.1", "IP of the node") port := flag.String("port", "9876", "port of the node.") console := flag.Bool("console_only", false, "Output to console only") @@ -104,6 +108,9 @@ func main() { logConn := flag.Bool("log_conn", false, "log incoming/outgoing connections") maxConnPerIP := flag.Int("max_conn_per_ip", 10, "max connections number for same ip") forceReachabilityPublic := flag.Bool("force_public", false, "forcing the local node to believe it is reachable externally") + noTransportSecurity := flag.Bool("no_transport_security", true, "disable TLS encrypted transport") + userAgent := flag.String("user_agent", defUserAgent, "explicitly set the user-agent, so we can differentiate from other Go libp2p users") + noRelay := flag.Bool("no_relay", true, "no relay services, direct connections between peers only") pprof := flag.Bool("pprof", false, "enabled pprof") pprofAddr := flag.String("pprof.addr", "127.0.0.1:6060", "http pprof address") @@ -140,6 +147,12 @@ func main() { DataStoreFile: &dataStorePath, MaxConnPerIP: *maxConnPerIP, ForceReachabilityPublic: *forceReachabilityPublic, + NoTransportSecurity: *noTransportSecurity, + NAT: true, + UserAgent: *userAgent, + DialTimeout: time.Minute, + MuxerType: p2p.Mplex, + NoRelay: *noRelay, }) if err != nil { utils.FatalErrMsg(err, "cannot initialize network") diff --git a/cmd/harmony/config_migrations.go b/cmd/harmony/config_migrations.go index 0db87d0748..20b6be42c6 100644 --- a/cmd/harmony/config_migrations.go +++ b/cmd/harmony/config_migrations.go @@ -416,6 +416,29 @@ func init() { return confTree } + migrations["2.6.1"] = func(confTree *toml.Tree) *toml.Tree { + if confTree.Get("P2P.NoTransportSecurity") == nil { + confTree.Set("P2P.NoTransportSecurity", defaultConfig.P2P.NoTransportSecurity) + } + if confTree.Get("P2P.NAT") == nil { + confTree.Set("P2P.NAT", defaultConfig.P2P.NAT) + } + if confTree.Get("P2P.UserAgent") == nil { + confTree.Set("P2P.UserAgent", defaultConfig.P2P.UserAgent) + } + if confTree.Get("P2P.DialTimeout") == nil { + confTree.Set("P2P.DialTimeout", defaultConfig.P2P.DialTimeout) + } + if confTree.Get("P2P.MuxerType") == nil { + confTree.Set("P2P.MuxerType", defaultConfig.P2P.MuxerType) + } + if confTree.Get("P2P.NoRelay") == nil { + confTree.Set("P2P.NoRelay", defaultConfig.P2P.NoRelay) + } + confTree.Set("Version", "2.6.2") + return confTree + } + // check that the latest version here is the same as in default.go largestKey := getNextVersion(migrations) if largestKey != tomlConfigVersion { diff --git a/cmd/harmony/default.go b/cmd/harmony/default.go index 217c7306f1..0bff21b35d 100644 --- a/cmd/harmony/default.go +++ b/cmd/harmony/default.go @@ -9,7 +9,7 @@ import ( nodeconfig "github.com/harmony-one/harmony/internal/configs/node" ) -const tomlConfigVersion = "2.6.1" +const tomlConfigVersion = "2.6.2" const ( defNetworkType = nodeconfig.Mainnet @@ -39,6 +39,12 @@ var defaultConfig = harmonyconfig.HarmonyConfig{ ConnManagerLowWatermark: nodeconfig.DefaultConnManagerLowWatermark, ConnManagerHighWatermark: nodeconfig.DefaultConnManagerHighWatermark, WaitForEachPeerToConnect: nodeconfig.DefaultWaitForEachPeerToConnect, + NoTransportSecurity: nodeconfig.DefaultNoTransportSecurity, + NAT: nodeconfig.DefaultNAT, + UserAgent: nodeconfig.DefaultUserAgent, + DialTimeout: nodeconfig.DefaultDialTimeout, + MuxerType: nodeconfig.DefaultMuxerType, + NoRelay: nodeconfig.DefaultNoRelay, }, HTTP: harmonyconfig.HttpConfig{ Enabled: true, diff --git a/cmd/harmony/flags.go b/cmd/harmony/flags.go index a52b7138ff..18c494243d 100644 --- a/cmd/harmony/flags.go +++ b/cmd/harmony/flags.go @@ -66,6 +66,11 @@ var ( maxPeersFlag, connManagerLowWatermarkFlag, connManagerHighWatermarkFlag, + noTransportSecurityFlag, + natFlag, + userAgentFlag, + muxerTypeFlag, + noRelayFlag, } httpFlags = []cli.Flag{ @@ -637,6 +642,31 @@ var ( Usage: "node waits for each single peer to connect and it doesn't add them to peers list after timeout", DefValue: defaultConfig.P2P.WaitForEachPeerToConnect, } + noTransportSecurityFlag = cli.BoolFlag{ + Name: "p2p.no-transport-security", + Usage: "disable TLS encrypted transport", + DefValue: defaultConfig.P2P.NoTransportSecurity, + } + natFlag = cli.BoolFlag{ + Name: "p2p.nat", + Usage: "enable NAT Manager. it takes care of setting NAT port mappings, and discovering external addresses", + DefValue: defaultConfig.P2P.NAT, + } + userAgentFlag = cli.StringFlag{ + Name: "p2p.user-agent", + Usage: "explicitly set the user-agent, so we can differentiate from other Go libp2p users", + DefValue: defaultConfig.P2P.UserAgent, + } + muxerTypeFlag = cli.IntFlag{ + Name: "p2p.muxer", + Usage: "protocol muxer to mux per-protocol streams (0:Mplex, 1:Yamux, default:0)", + DefValue: defaultConfig.P2P.MuxerType, + } + noRelayFlag = cli.BoolFlag{ + Name: "p2p.no-relay", + Usage: "no relay services, direct connections between peers only", + DefValue: defaultConfig.P2P.NoRelay, + } ) func applyP2PFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { @@ -688,6 +718,26 @@ func applyP2PFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { if cli.IsFlagChanged(cmd, p2pDisablePrivateIPScanFlag) { config.P2P.DisablePrivateIPScan = cli.GetBoolFlagValue(cmd, p2pDisablePrivateIPScanFlag) } + + if cli.IsFlagChanged(cmd, noTransportSecurityFlag) { + config.P2P.NoTransportSecurity = cli.GetBoolFlagValue(cmd, noTransportSecurityFlag) + } + + if cli.IsFlagChanged(cmd, natFlag) { + config.P2P.NAT = cli.GetBoolFlagValue(cmd, natFlag) + } + + if cli.IsFlagChanged(cmd, userAgentFlag) { + config.P2P.UserAgent = cli.GetStringFlagValue(cmd, userAgentFlag) + } + + if cli.IsFlagChanged(cmd, muxerTypeFlag) { + config.P2P.MuxerType = cli.GetIntFlagValue(cmd, muxerTypeFlag) + } + + if cli.IsFlagChanged(cmd, noRelayFlag) { + config.P2P.NoRelay = cli.GetBoolFlagValue(cmd, noRelayFlag) + } } // http flags diff --git a/cmd/harmony/flags_test.go b/cmd/harmony/flags_test.go index 50ed02fa29..53971fc1d2 100644 --- a/cmd/harmony/flags_test.go +++ b/cmd/harmony/flags_test.go @@ -70,6 +70,12 @@ func TestHarmonyFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, HTTP: harmonyconfig.HttpConfig{ Enabled: true, @@ -410,6 +416,12 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, }, { @@ -424,6 +436,12 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, }, { @@ -439,6 +457,12 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, }, { @@ -454,6 +478,12 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, }, { @@ -469,6 +499,12 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, }, { @@ -484,6 +520,12 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: 100, ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, }, }, { @@ -499,6 +541,138 @@ func TestP2PFlags(t *testing.T) { ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, ConnManagerHighWatermark: 400, WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, + }, + }, + { + args: []string{"--p2p.connmgr-high", "400"}, + expConfig: harmonyconfig.P2pConfig{ + Port: nodeconfig.DefaultP2PPort, + IP: nodeconfig.DefaultPublicListenIP, + KeyFile: "./.hmykey", + DiscConcurrency: nodeconfig.DefaultP2PConcurrency, + MaxConnsPerIP: nodeconfig.DefaultMaxConnPerIP, + DisablePrivateIPScan: defaultConfig.P2P.DisablePrivateIPScan, + MaxPeers: defaultConfig.P2P.MaxPeers, + ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, + ConnManagerHighWatermark: 400, + WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, + }, + }, + { + args: []string{"--p2p.no-transport-security=false"}, + expConfig: harmonyconfig.P2pConfig{ + Port: nodeconfig.DefaultP2PPort, + IP: nodeconfig.DefaultPublicListenIP, + KeyFile: "./.hmykey", + DiscConcurrency: nodeconfig.DefaultP2PConcurrency, + MaxConnsPerIP: nodeconfig.DefaultMaxConnPerIP, + DisablePrivateIPScan: defaultConfig.P2P.DisablePrivateIPScan, + MaxPeers: defaultConfig.P2P.MaxPeers, + ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, + ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, + WaitForEachPeerToConnect: false, + NoTransportSecurity: false, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, + }, + }, + { + args: []string{"--p2p.nat=false"}, + expConfig: harmonyconfig.P2pConfig{ + Port: nodeconfig.DefaultP2PPort, + IP: nodeconfig.DefaultPublicListenIP, + KeyFile: "./.hmykey", + DiscConcurrency: nodeconfig.DefaultP2PConcurrency, + MaxConnsPerIP: nodeconfig.DefaultMaxConnPerIP, + DisablePrivateIPScan: defaultConfig.P2P.DisablePrivateIPScan, + MaxPeers: defaultConfig.P2P.MaxPeers, + ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, + ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, + WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: false, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, + }, + }, + { + args: []string{"--p2p.user-agent", "test1"}, + expConfig: harmonyconfig.P2pConfig{ + Port: nodeconfig.DefaultP2PPort, + IP: nodeconfig.DefaultPublicListenIP, + KeyFile: "./.hmykey", + DiscConcurrency: nodeconfig.DefaultP2PConcurrency, + MaxConnsPerIP: nodeconfig.DefaultMaxConnPerIP, + DisablePrivateIPScan: defaultConfig.P2P.DisablePrivateIPScan, + MaxPeers: defaultConfig.P2P.MaxPeers, + ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, + ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, + WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: "test1", + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: defaultConfig.P2P.NoRelay, + }, + }, + { + args: []string{"--p2p.muxer", "1"}, + expConfig: harmonyconfig.P2pConfig{ + Port: nodeconfig.DefaultP2PPort, + IP: nodeconfig.DefaultPublicListenIP, + KeyFile: "./.hmykey", + DiscConcurrency: nodeconfig.DefaultP2PConcurrency, + MaxConnsPerIP: nodeconfig.DefaultMaxConnPerIP, + DisablePrivateIPScan: defaultConfig.P2P.DisablePrivateIPScan, + MaxPeers: defaultConfig.P2P.MaxPeers, + ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, + ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, + WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: 1, + NoRelay: defaultConfig.P2P.NoRelay, + }, + }, + { + args: []string{"--p2p.no-relay=false"}, + expConfig: harmonyconfig.P2pConfig{ + Port: nodeconfig.DefaultP2PPort, + IP: nodeconfig.DefaultPublicListenIP, + KeyFile: "./.hmykey", + DiscConcurrency: nodeconfig.DefaultP2PConcurrency, + MaxConnsPerIP: nodeconfig.DefaultMaxConnPerIP, + DisablePrivateIPScan: defaultConfig.P2P.DisablePrivateIPScan, + MaxPeers: defaultConfig.P2P.MaxPeers, + ConnManagerLowWatermark: defaultConfig.P2P.ConnManagerLowWatermark, + ConnManagerHighWatermark: defaultConfig.P2P.ConnManagerHighWatermark, + WaitForEachPeerToConnect: false, + NoTransportSecurity: defaultConfig.P2P.NoTransportSecurity, + NAT: defaultConfig.P2P.NAT, + UserAgent: defaultConfig.P2P.UserAgent, + DialTimeout: defaultConfig.P2P.DialTimeout, + MuxerType: defaultConfig.P2P.MuxerType, + NoRelay: false, }, }, } diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index 31332b2e6e..eb0d2183af 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -701,6 +701,12 @@ func createGlobalConfig(hc harmonyconfig.HarmonyConfig) (*nodeconfig.ConfigType, ConnManagerHighWatermark: hc.P2P.ConnManagerHighWatermark, WaitForEachPeerToConnect: hc.P2P.WaitForEachPeerToConnect, ForceReachabilityPublic: forceReachabilityPublic, + NoTransportSecurity: hc.P2P.NoTransportSecurity, + NAT: hc.P2P.NAT, + UserAgent: hc.P2P.UserAgent, + DialTimeout: hc.P2P.DialTimeout, + MuxerType: p2p.MuxerType(hc.P2P.MuxerType), + NoRelay: hc.P2P.NoRelay, }) if err != nil { return nil, errors.Wrap(err, "cannot create P2P network host") diff --git a/go.mod b/go.mod index ac5fecc538..168870584d 100644 --- a/go.mod +++ b/go.mod @@ -181,6 +181,7 @@ require ( github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect github.com/libp2p/go-libp2p-record v0.2.0 // indirect + github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect diff --git a/go.sum b/go.sum index 4f620c9014..936af88d25 100644 --- a/go.sum +++ b/go.sum @@ -895,6 +895,8 @@ github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhr github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= +github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= @@ -1433,6 +1435,7 @@ github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= +github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= diff --git a/internal/configs/harmony/harmony.go b/internal/configs/harmony/harmony.go index 276c90d05a..719fa48ffe 100644 --- a/internal/configs/harmony/harmony.go +++ b/internal/configs/harmony/harmony.go @@ -125,6 +125,18 @@ type P2pConfig struct { ConnManagerLowWatermark int ConnManagerHighWatermark int WaitForEachPeerToConnect bool + // to disable p2p security (tls and noise) + NoTransportSecurity bool + // enable p2p NAT. NAT Manager takes care of setting NAT port mappings, and discovering external addresses + NAT bool + // custom user agent; explicitly set the user-agent, so we can differentiate from other Go libp2p users + UserAgent string + // p2p dial timeout + DialTimeout time.Duration + // P2P multiplexer type (default:Mplex, 0:Mplex, 1:Yamux) + MuxerType int + // No relay services, direct connections between peers only + NoRelay bool } type GeneralConfig struct { diff --git a/internal/configs/node/network.go b/internal/configs/node/network.go index 03f1472125..cef4d838e4 100644 --- a/internal/configs/node/network.go +++ b/internal/configs/node/network.go @@ -1,5 +1,7 @@ package nodeconfig +import "time" + var ( mainnetBootNodes = []string{ "/dnsaddr/bootstrap.t.hmny.io", @@ -77,6 +79,18 @@ const ( DefaultConnManagerHighWatermark = 192 // DefaultWaitForEachPeerToConnect sets the sync configs to connect to neighbor peers one by one and waits for each peer to connect. DefaultWaitForEachPeerToConnect = false + // DefaultNoTransportSecurity + DefaultNoTransportSecurity = true + // DefaultNAT enables NAT manager for P2P + DefaultNAT = true + // DefaultUserAgent set the user agent to differentiate between libp2p users + DefaultUserAgent = "" + // DefaultDialTimeout dial timeout + DefaultDialTimeout = time.Minute + // DefaultMuxerType P2P multiplexer type (default:Mplex, 0:Mplex, 1:Yamux) + DefaultMuxerType = 0 // 0:Mplex 1:Yamux + // DefaultNoRelay disables p2p host relay + DefaultNoRelay = true ) const ( diff --git a/p2p/host.go b/p2p/host.go index 4a4240c565..db75efbf1d 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -20,22 +20,28 @@ import ( sttypes "github.com/harmony-one/harmony/p2p/stream/types" "github.com/libp2p/go-libp2p" dht "github.com/libp2p/go-libp2p-kad-dht" + libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub" libp2p_config "github.com/libp2p/go-libp2p/config" libp2p_crypto "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/host" libp2p_host "github.com/libp2p/go-libp2p/core/host" libp2p_network "github.com/libp2p/go-libp2p/core/network" libp2p_peer "github.com/libp2p/go-libp2p/core/peer" libp2p_peerstore "github.com/libp2p/go-libp2p/core/peerstore" "github.com/libp2p/go-libp2p/core/protocol" - "github.com/libp2p/go-libp2p/core/routing" "github.com/libp2p/go-libp2p/p2p/net/connmgr" - "github.com/libp2p/go-libp2p/p2p/security/noise" - libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls" + "github.com/libp2p/go-libp2p/p2p/transport/tcp" ma "github.com/multiformats/go-multiaddr" "github.com/pkg/errors" "github.com/rs/zerolog" + + "github.com/libp2p/go-libp2p/core/sec/insecure" + basichost "github.com/libp2p/go-libp2p/p2p/host/basic" + mplex "github.com/libp2p/go-libp2p/p2p/muxer/mplex" + yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux" + noise "github.com/libp2p/go-libp2p/p2p/security/noise" + tls "github.com/libp2p/go-libp2p/p2p/security/tls" + madns "github.com/multiformats/go-multiaddr-dns" ) type ConnectCallback func(net libp2p_network.Network, conn libp2p_network.Conn) error @@ -85,6 +91,14 @@ const ( MaxMessageSize = 1 << 21 ) +// Host Multiplexer's Type +type MuxerType int + +const ( + Mplex MuxerType = iota + Yamux +) + // HostConfig is the config structure to create a new host type HostConfig struct { Self *Peer @@ -99,6 +113,12 @@ type HostConfig struct { ConnManagerHighWatermark int WaitForEachPeerToConnect bool ForceReachabilityPublic bool + NoTransportSecurity bool + NAT bool + UserAgent string + DialTimeout time.Duration + MuxerType MuxerType + NoRelay bool } func init() { @@ -124,64 +144,98 @@ func NewHost(cfg HostConfig) (Host, error) { addr := fmt.Sprintf("/ip4/%s/tcp/%s", self.IP, self.Port) listenAddr := libp2p.ListenAddrStrings( - addr, // regular tcp connections - addr+"/quic", // a UDP endpoint for the QUIC transport + addr, // regular tcp connections ) + // transporters + tcpTransport := libp2p.Transport( + tcp.NewTCPTransport, + tcp.WithConnectionTimeout(time.Minute*60)) // break unused connections + + // create NAT Manager; it takes care of setting NAT port mappings, and discovering external addresses + var nat libp2p_config.NATManagerC // disabled if nil + if cfg.NAT { + nat = basichost.NewNATManager + } + ctx, cancel := context.WithCancel(context.Background()) // create connection manager low := cfg.ConnManagerLowWatermark high := cfg.ConnManagerHighWatermark - if high < low { + connMngr, err := connectionManager(low, high) + if err != nil { cancel() - utils.Logger().Error(). - Int("low", cfg.ConnManagerLowWatermark). - Int("high", cfg.ConnManagerHighWatermark). - Msg("connection manager watermarks are invalid") - return nil, errors.New("invalid connection manager watermarks") + return nil, fmt.Errorf("failed to open connection manager: %w", err) + } + + // relay + var relay libp2p_config.Option + if cfg.NoRelay { + relay = libp2p.DisableRelay() // No relay services, direct connections between peers only. + } else { + relay = libp2p.EnableRelayService() + } + + // set dial timeout + dto := cfg.DialTimeout + if dto <= 0 { + dto = time.Minute } // prepare host options var idht *dht.IpfsDHT - var opt discovery.DHTConfig p2pHostConfig := []libp2p.Option{ - listenAddr, libp2p.Identity(key), - // Support TLS connections - libp2p.Security(libp2ptls.ID, libp2ptls.New), - // Support noise connections - libp2p.Security(noise.ID, noise.New), - // Support any other default transports (TCP) - libp2p.DefaultTransports, - // Prevent the peer from having too many - // connections by attaching a connection manager. - connectionManager(low, high), - // Attempt to open ports using uPNP for NATed hosts. - libp2p.NATPortMap(), - libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) { - opt = discovery.DHTConfig{ - BootNodes: cfg.BootNodes, - DataStoreFile: cfg.DataStoreFile, - DiscConcurrency: cfg.DiscConcurrency, - } - opts, err := opt.GetLibp2pRawOptions() - if err != nil { - return nil, err - } - idht, err = dht.New(ctx, h, opts...) - return idht, err - }), - // To help other peers to figure out if they are behind - // NATs, launch the server-side of AutoNAT too (AutoRelay - // already runs the client) - // This service is highly rate-limited and should not cause any - // performance issues. + // Explicitly set the user-agent, so we can differentiate from other Go libp2p users. + libp2p.UserAgent(cfg.UserAgent), + // regular tcp connections + tcpTransport, + // dial timeout + libp2p.WithDialTimeout(dto), + // No relay services, direct connections between peers only. + relay, + // host will start and listen to network directly after construction from config. + listenAddr, + /* + libp2p.ConnectionGater(connGtr), // TODO use connection gater to monitor the connections + libp2p.ResourceManager(nil), // TODO use resource manager interface to manage resources per peer better + libp2p.Peerstore(ps), // TODO add extended peer store + */ + // Connection manager + connMngr, + // NAT manager + libp2p.NATManager(nat), + // Band width Reporter + libp2p.BandwidthReporter(newCounter()), // may be nil if disabled + // Resolver + libp2p.MultiaddrResolver(madns.DefaultResolver), + // Ping is a small built-in libp2p protocol that helps us check/debug latency between peers. + libp2p.Ping(true), + // Help peers with their NAT reachability status, but throttle to avoid too much work. libp2p.EnableNATService(), - // Bandwidth Reporter - libp2p.BandwidthReporter(newCounter()), - // Enable relay service, to disable relay we can use libp2p.DisableRelay() - libp2p.EnableRelayService(), + // NAT Rate Limiter + libp2p.AutoNATServiceRateLimit(10, 5, time.Second*60), + } + + // Set host security + if cfg.NoTransportSecurity { + p2pHostConfig = append(p2pHostConfig, libp2p.Security(insecure.ID, insecure.NewWithIdentity)) + } else { + p2pHostConfig = append(p2pHostConfig, NoiseC(), TlsC()) + } + + // Set Muxer (default: Mplex) + switch cfg.MuxerType { + case Yamux: + p2pHostConfig = append(p2pHostConfig, YamuxC()) + case Mplex: + p2pHostConfig = append(p2pHostConfig, MplexC()) + default: + utils.Logger().Error(). + Interface("muxer", cfg.MuxerType). + Msg("Muxer type is invalid, it is set on default value (mplex)") + p2pHostConfig = append(p2pHostConfig, MplexC()) } if cfg.ForceReachabilityPublic { @@ -202,6 +256,22 @@ func NewHost(cfg HostConfig) (Host, error) { return nil, errors.Wrapf(err, "cannot initialize libp2p host") } + // DHT + opt := discovery.DHTConfig{ + BootNodes: cfg.BootNodes, + DataStoreFile: cfg.DataStoreFile, + DiscConcurrency: cfg.DiscConcurrency, + } + opts, err := opt.GetLibp2pRawOptions() + if err != nil { + cancel() + return nil, errors.Wrapf(err, "initialize libp2p raw options failed") + } + idht, errDHT := dht.New(ctx, p2pHost, opts...) + if errDHT != nil { + cancel() + return nil, errors.Wrapf(errDHT, "cannot initialize libp2p DHT") + } disc, err := discovery.NewDHTDiscovery(ctx, cancel, p2pHost, idht, opt) if err != nil { cancel() @@ -209,6 +279,7 @@ func NewHost(cfg HostConfig) (Host, error) { return nil, errors.Wrap(err, "cannot create DHT discovery") } + // Gossip Pub Sub options := []libp2p_pubsub.Option{ // WithValidateQueueSize sets the buffer of validate queue. Defaults to 32. When queue is full, validation is throttled and new messages are dropped. libp2p_pubsub.WithValidateQueueSize(512), @@ -280,31 +351,50 @@ func NewHost(cfg HostConfig) (Host, error) { return h, nil } +func YamuxC() libp2p.Option { + return libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport) +} + +func MplexC() libp2p.Option { + return libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport) +} + +func NoiseC() libp2p.Option { + return libp2p.Security(noise.ID, noise.New) +} + +func TlsC() libp2p.Option { + return libp2p.Security(tls.ID, tls.New) +} + // connectionManager creates a new connection manager and configures libp2p to use the // given connection manager. // lo and hi are watermarks governing the number of connections that'll be maintained. // When the peer count exceeds the 'high watermark', as many peers will be pruned (and // their connections terminated) until 'low watermark' peers remain. -func connectionManager(low int, high int) libp2p_config.Option { - if low > 0 && high > low { - connmgr, err := connmgr.NewConnManager( - low, // Low Watermark - high, // High Watermark - connmgr.WithGracePeriod(time.Minute), - ) - if err != nil { - utils.Logger().Error(). - Err(err). - Int("low", low). - Int("high", high). - Msg("create connection manager failed") - return nil - } - return libp2p.ConnectionManager(connmgr) +func connectionManager(low int, high int) (libp2p_config.Option, error) { + if low < 0 || high < low { + utils.Logger().Error(). + Int("low", low). + Int("high", high). + Msg("connection manager watermarks are invalid") + return nil, errors.New("invalid connection manager watermarks") } - return func(p2pConfig *libp2p_config.Config) error { - return nil + connmgr, err := connmgr.NewConnManager( + low, // Low Watermark + high, // High Watermark + connmgr.WithGracePeriod(time.Minute), + connmgr.WithSilencePeriod(time.Minute), + connmgr.WithEmergencyTrim(true)) + if err != nil { + utils.Logger().Error(). + Err(err). + Int("low", low). + Int("high", high). + Msg("create connection manager failed") + return nil, err } + return libp2p.ConnectionManager(connmgr), nil } // HostV2 is the version 2 p2p host From 8abcc745896f783a9e615644eed66f2439d05e2b Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Sat, 25 May 2024 18:23:58 -0400 Subject: [PATCH 19/66] Fix for crosslink snap db. (#4675) * Fix for crosslink snap db. * Fix for possible race for new block post consensus job. --- node/node_newblock.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/node/node_newblock.go b/node/node_newblock.go index c00a8cd414..05157e0237 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -248,6 +248,16 @@ func (node *Node) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error) AnErr("[ProposeNewBlock] pending crosslink is already committed onchain", err) continue } + last, err := node.Blockchain().ReadShardLastCrossLink(pending.ShardID()) + if err != nil { + utils.Logger().Debug(). + AnErr("[ProposeNewBlock] failed to read last crosslink", err) + // no return + } + // if pending crosslink is older than the last crosslink, delete it and continue + if err == nil && exist == nil && last != nil && last.BlockNum() >= pending.BlockNum() { + invalidToDelete = append(invalidToDelete, pending) + } // Crosslink is already verified before it's accepted to pending, // no need to verify again in proposal. From 338ff01b46c78a9347e55adb7082ba74af68ee94 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Mon, 27 May 2024 00:28:15 -0400 Subject: [PATCH 20/66] Removed threshold 10 epochs. (#4671) --- node/node_newblock.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/node/node_newblock.go b/node/node_newblock.go index 05157e0237..657d847114 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -1,7 +1,6 @@ package node import ( - "math/big" "sort" "strings" "time" @@ -228,18 +227,11 @@ func (node *Node) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error) utils.AnalysisStart("proposeNewBlockVerifyCrossLinks") // Prepare cross links and slashing messages var crossLinksToPropose types.CrossLinks - ten := big.NewInt(10) - crossLinkEpochThreshold := new(big.Int).Sub(currentHeader.Epoch(), ten) if isBeaconchainInCrossLinkEra { allPending, err := node.Blockchain().ReadPendingCrossLinks() invalidToDelete := []types.CrossLink{} if err == nil { for _, pending := range allPending { - // if pending crosslink is older than 10 epochs, delete it and continue. this logic is also applied when the node starts - if pending.EpochF.Cmp(crossLinkEpochThreshold) <= 0 { - invalidToDelete = append(invalidToDelete, pending) - continue - } // ReadCrossLink beacon chain usage. exist, err := node.Blockchain().ReadCrossLink(pending.ShardID(), pending.BlockNum()) if err == nil || exist != nil { From c148e5f0b61e7d2ab48ca49862081f28699279f5 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Mon, 27 May 2024 05:45:07 -0400 Subject: [PATCH 21/66] Extracts `GetAddressForBLSKey` functionality from `Node` struct. (#4642) * Extracts `GetAddressForBLSKey` functionality from `Node` struct. * Fix for panic. --- cmd/harmony/main.go | 1 + go.mod | 6 +-- go.sum | 4 -- internal/registry/registry.go | 65 ++++++++++++++++++++---- node/addresses.go | 94 +++++++++++++++++++++++++++++++++++ node/node.go | 81 +----------------------------- node/node_handler.go | 26 +++++++--- node/node_newblock.go | 9 ++-- shard/shard_state.go | 1 + 9 files changed, 181 insertions(+), 106 deletions(-) create mode 100644 node/addresses.go diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index eb0d2183af..104cfb700b 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -883,6 +883,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()) diff --git a/go.mod b/go.mod index 168870584d..2a808e818e 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 936af88d25..7cff65a977 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/registry/registry.go b/internal/registry/registry.go index 50398bc5ca..cb5729e926 100644 --- a/internal/registry/registry.go +++ b/internal/registry/registry.go @@ -1,25 +1,33 @@ package registry 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/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 +168,42 @@ 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 FindCommitteeByID interface { + FindCommitteeByID(shardID uint32) (*shard.Committee, error) +} + +type AddressToBLSKey interface { + GetAddressForBLSKey(publicKeys multibls.PublicKeys, shardState FindCommitteeByID, blskey *bls_core.PublicKey, epoch *big.Int) common.Address + GetAddresses(publicKeys multibls.PublicKeys, shardState FindCommitteeByID, epoch *big.Int) map[string]common.Address +} diff --git a/node/addresses.go b/node/addresses.go new file mode 100644 index 0000000000..44279981c2 --- /dev/null +++ b/node/addresses.go @@ -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/registry" + "github.com/harmony-one/harmony/internal/utils" + "github.com/harmony-one/harmony/internal/utils/lrucache" + "github.com/harmony-one/harmony/multibls" +) + +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 registry.FindCommitteeByID, blskey *bls_core.PublicKey, epoch *big.Int) common.Address { + return a.GetAddresses(publicKeys, shardState, epoch)[blskey.SerializeToHexStr()] +} + +// GetAddresses retrieves all ECDSA addresses of the bls keys for epoch +func (a *AddressToBLSKey) GetAddresses(publicKeys multibls.PublicKeys, shardState registry.FindCommitteeByID, epoch *big.Int) map[string]common.Address { + // populate if new epoch + if rs, ok := a.keysToAddrs.Get(epoch.Uint64()); ok { + return rs + } + a.keysToAddrsMutex.Lock() + a.populateSelfAddresses(publicKeys, shardState, epoch) + a.keysToAddrsMutex.Unlock() + if rs, ok := a.keysToAddrs.Get(epoch.Uint64()); ok { + return rs + } + return make(map[string]common.Address) +} + +func (a *AddressToBLSKey) populateSelfAddresses(publicKeys multibls.PublicKeys, shardState registry.FindCommitteeByID, 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) +} diff --git a/node/node.go b/node/node.go index d8a8e8e6fd..1b4cb69142 100644 --- a/node/node.go +++ b/node/node.go @@ -14,7 +14,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" "github.com/harmony-one/abool" - 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" proto_node "github.com/harmony-one/harmony/api/proto/node" @@ -27,7 +26,6 @@ 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" @@ -37,7 +35,6 @@ import ( "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/internal/utils/lrucache" "github.com/harmony-one/harmony/node/worker" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/shard" @@ -124,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 @@ -1025,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") @@ -1299,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 diff --git a/node/node_handler.go b/node/node_handler.go index b745ca7136..011d5d0771 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -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, newBlock.Epoch()) { 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) diff --git a/node/node_newblock.go b/node/node_newblock.go index 657d847114..107c36247d 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -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, header.Epoch()) beneficiary = coinbase ) @@ -296,7 +300,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 { diff --git a/shard/shard_state.go b/shard/shard_state.go index 8b8ca6f145..60a6e1341e 100644 --- a/shard/shard_state.go +++ b/shard/shard_state.go @@ -26,6 +26,7 @@ var ( // State is the collection of all committees type State struct { + // Epoch can be nil Epoch *big.Int `json:"epoch"` Shards []Committee `json:"shards"` } From a7560fed6ca312ab6b45bc3f47939a5d2515806d Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Mon, 27 May 2024 23:50:13 -0400 Subject: [PATCH 22/66] Crosslink heartbeat verify through current committee (#4673) * Fixed crosslink sending. * Removed threshold 10 epochs. * Fix. * Fixed crosslink issue. * Additional error log. --- core/types/crosslink_heartbeat.go | 7 +++--- node/node_cross_link.go | 36 ++++++++++++++++++------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/core/types/crosslink_heartbeat.go b/core/types/crosslink_heartbeat.go index 2ef9dbf666..f30f28c18a 100644 --- a/core/types/crosslink_heartbeat.go +++ b/core/types/crosslink_heartbeat.go @@ -3,7 +3,8 @@ package types type CrosslinkHeartbeat struct { ShardID uint32 LatestContinuousBlockNum uint64 - Epoch uint64 - PublicKey []byte - Signature []byte + //Deprecated + Epoch uint64 + PublicKey []byte + Signature []byte } diff --git a/node/node_cross_link.go b/node/node_cross_link.go index d0f80545d5..61b57a4fff 100644 --- a/node/node_cross_link.go +++ b/node/node_cross_link.go @@ -1,8 +1,6 @@ package node import ( - "math/big" - common2 "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" ffi_bls "github.com/harmony-one/bls/ffi/go/bls" @@ -14,6 +12,8 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +var CrosslinkOutdatedErr = errors.New("crosslink signal is outdated") + const ( maxPendingCrossLinkSize = 1000 crossLinkBatchSize = 3 @@ -32,34 +32,35 @@ func (node *Node) processCrossLinkHeartbeatMessage(msgPayload []byte) error { hb := types.CrosslinkHeartbeat{} err := rlp.DecodeBytes(msgPayload, &hb) if err != nil { - return err + return errors.WithMessagef(err, "cannot decode crosslink heartbeat message, len: %d", len(msgPayload)) } - shardID := node.Blockchain().CurrentBlock().ShardID() + cur := node.Blockchain().CurrentBlock() + shardID := cur.ShardID() if hb.ShardID != shardID { return errors.Errorf("invalid shard id: expected %d, got %d", shardID, hb.ShardID) } // Outdated signal. if s := node.crosslinks.LastKnownCrosslinkHeartbeatSignal(); s != nil && s.LatestContinuousBlockNum > hb.LatestContinuousBlockNum { - return nil + return errors.WithMessagef(CrosslinkOutdatedErr, "latest continuous block num: %d, got %d", s.LatestContinuousBlockNum, hb.LatestContinuousBlockNum) } sig := &ffi_bls.Sign{} err = sig.Deserialize(hb.Signature) if err != nil { - return err + return errors.WithMessagef(err, "cannot deserialize signature, len: %d", len(hb.Signature)) } hb.Signature = nil serialized, err := rlp.EncodeToBytes(hb) if err != nil { - return err + return errors.WithMessage(err, "cannot serialize crosslink heartbeat message") } pub := ffi_bls.PublicKey{} err = pub.Deserialize(hb.PublicKey) if err != nil { - return err + return errors.WithMessagef(err, "cannot deserialize public key, len: %d", len(hb.PublicKey)) } ok := sig.VerifyHash(&pub, serialized) @@ -67,18 +68,17 @@ func (node *Node) processCrossLinkHeartbeatMessage(msgPayload []byte) error { return errors.New("invalid signature") } - state, err := node.EpochChain().ReadShardState(big.NewInt(int64(hb.Epoch))) + state, err := node.EpochChain().ReadShardState(cur.Epoch()) if err != nil { - return err + return errors.WithMessagef(err, "cannot read shard state for epoch %d", cur.Epoch()) } - committee, err := state.FindCommitteeByID(shard.BeaconChainShardID) if err != nil { - return err + return errors.WithMessagef(err, "cannot find committee for shard %d", shard.BeaconChainShardID) } pubs, err := committee.BLSPublicKeys() if err != nil { - return err + return errors.WithMessage(err, "cannot get BLS public keys") } keyExists := false @@ -90,7 +90,7 @@ func (node *Node) processCrossLinkHeartbeatMessage(msgPayload []byte) error { } if !keyExists { - return errors.New("pub key doesn't exist") + return errors.Errorf("pub key %s not found in committiee for epoch %d and shard %d, my current shard is %d, pub keys len %d", pub.SerializeToHexStr(), hb.Epoch, shard.BeaconChainShardID, shardID, len(pubs)) } utils.Logger().Info(). @@ -103,7 +103,13 @@ func (node *Node) processCrossLinkHeartbeatMessage(msgPayload []byte) error { func (node *Node) ProcessCrossLinkMessage(msgPayload []byte) { if node.IsRunningBeaconChain() { pendingCLs, err := node.Blockchain().ReadPendingCrossLinks() - if err == nil && len(pendingCLs) >= maxPendingCrossLinkSize { + if err != nil { + utils.Logger().Debug(). + Err(err). + Msgf("[ProcessingCrossLink] Pending Crosslink reach maximum size: %d", len(pendingCLs)) + return + } + if len(pendingCLs) >= maxPendingCrossLinkSize { utils.Logger().Debug(). Msgf("[ProcessingCrossLink] Pending Crosslink reach maximum size: %d", len(pendingCLs)) return From a8a2a1391c07371f937c934c0c6ed5abda1afb63 Mon Sep 17 00:00:00 2001 From: "Nita Neou (Soph)" Date: Wed, 29 May 2024 12:08:16 +0700 Subject: [PATCH 23/66] Update testnet internal vote power back to 90% --- internal/configs/sharding/testnet.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/configs/sharding/testnet.go b/internal/configs/sharding/testnet.go index f640857537..f598216301 100644 --- a/internal/configs/sharding/testnet.go +++ b/internal/configs/sharding/testnet.go @@ -42,6 +42,8 @@ const ( func (ts testnetSchedule) InstanceForEpoch(epoch *big.Int) Instance { switch { + case epoch.Cmp(big.NewInt(3388)) >= 0: // one time fix for devnet shard 1 down, estimated 30 May 7:50AM UTC + return testnetV6_1 case params.TestnetChainConfig.IsTestnetExternalEpoch(epoch): return testnetV6 case params.TestnetChainConfig.IsHIP30(epoch): @@ -179,4 +181,12 @@ var ( hip30CollectionAddressTestnet, testnetReshardingEpoch, TestnetSchedule.BlocksPerEpoch(), ) + testnetV6_1 = MustNewInstance( + 2, 30, 0, 0, + numeric.MustNewDecFromStr("0.9"), genesis.TNHarmonyAccountsV1, + genesis.TNFoundationalAccounts, emptyAllowlist, + feeCollectorsTestnet, numeric.MustNewDecFromStr("0.25"), + hip30CollectionAddressTestnet, testnetReshardingEpoch, + TestnetSchedule.BlocksPerEpoch(), + ) ) From 905bf58321757b2d67953cb1810c3d614bf462dc Mon Sep 17 00:00:00 2001 From: "Nita Neou (Soph)" Date: Thu, 30 May 2024 16:38:40 +0700 Subject: [PATCH 24/66] [testnet] add harmony internal node in sharding config --- internal/configs/sharding/testnet.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/configs/sharding/testnet.go b/internal/configs/sharding/testnet.go index f598216301..6a957ec820 100644 --- a/internal/configs/sharding/testnet.go +++ b/internal/configs/sharding/testnet.go @@ -42,6 +42,8 @@ const ( func (ts testnetSchedule) InstanceForEpoch(epoch *big.Int) Instance { switch { + case epoch.Cmp(big.NewInt(3392)) >= 0: // add harmony node, estimated 31 May 2:20AM UTC + return testnetV6_2 case epoch.Cmp(big.NewInt(3388)) >= 0: // one time fix for devnet shard 1 down, estimated 30 May 7:50AM UTC return testnetV6_1 case params.TestnetChainConfig.IsTestnetExternalEpoch(epoch): @@ -189,4 +191,12 @@ var ( hip30CollectionAddressTestnet, testnetReshardingEpoch, TestnetSchedule.BlocksPerEpoch(), ) + testnetV6_2 = MustNewInstance( + 2, 30, 8, 0, + numeric.MustNewDecFromStr("0.9"), genesis.TNHarmonyAccountsV1, + genesis.TNFoundationalAccounts, emptyAllowlist, + feeCollectorsTestnet, numeric.MustNewDecFromStr("0.25"), + hip30CollectionAddressTestnet, testnetReshardingEpoch, + TestnetSchedule.BlocksPerEpoch(), + ) ) From 7233e1ff195cb186f92fad06afb4fd844ddb3770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CGheisMohammadi=E2=80=9D?= <36589218+GheisMohammadi@users.noreply.github.com> Date: Thu, 30 May 2024 03:33:51 +0800 Subject: [PATCH 25/66] add muxer flag to bootnode --- cmd/bootnode/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 1802f478a8..995ce64872 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -109,6 +109,7 @@ func main() { maxConnPerIP := flag.Int("max_conn_per_ip", 10, "max connections number for same ip") forceReachabilityPublic := flag.Bool("force_public", false, "forcing the local node to believe it is reachable externally") noTransportSecurity := flag.Bool("no_transport_security", true, "disable TLS encrypted transport") + muxerType := flag.Int("muxer", 0, "protocol muxer to mux per-protocol streams (0:Mplex, 1:Yamux, default:0)") userAgent := flag.String("user_agent", defUserAgent, "explicitly set the user-agent, so we can differentiate from other Go libp2p users") noRelay := flag.Bool("no_relay", true, "no relay services, direct connections between peers only") @@ -151,7 +152,7 @@ func main() { NAT: true, UserAgent: *userAgent, DialTimeout: time.Minute, - MuxerType: p2p.Mplex, + MuxerType: p2p.MuxerType(*muxerType), NoRelay: *noRelay, }) if err != nil { From 7d06fdc0ce649e9273b2ba6e48a53b0fd7f78113 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Mon, 3 Jun 2024 10:25:18 +0330 Subject: [PATCH 26/66] add support for multiple muxers to p2p host (#4682) * change muxer flag to string to support multiple muxers * fixed muxer usage description --- cmd/bootnode/main.go | 4 +-- cmd/harmony/config_migrations.go | 4 +-- cmd/harmony/default.go | 2 +- cmd/harmony/flags.go | 12 ++++----- cmd/harmony/flags_test.go | 30 +++++++++++----------- cmd/harmony/main.go | 2 +- internal/configs/harmony/harmony.go | 4 +-- internal/configs/node/network.go | 4 +-- p2p/host.go | 39 +++++++++++++---------------- 9 files changed, 49 insertions(+), 52 deletions(-) diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 995ce64872..dfd503b3d1 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -109,7 +109,7 @@ func main() { maxConnPerIP := flag.Int("max_conn_per_ip", 10, "max connections number for same ip") forceReachabilityPublic := flag.Bool("force_public", false, "forcing the local node to believe it is reachable externally") noTransportSecurity := flag.Bool("no_transport_security", true, "disable TLS encrypted transport") - muxerType := flag.Int("muxer", 0, "protocol muxer to mux per-protocol streams (0:Mplex, 1:Yamux, default:0)") + muxer := flag.String("muxer", "mplex, yamux", "protocol muxer to mux per-protocol streams (mplex, yamux)") userAgent := flag.String("user_agent", defUserAgent, "explicitly set the user-agent, so we can differentiate from other Go libp2p users") noRelay := flag.Bool("no_relay", true, "no relay services, direct connections between peers only") @@ -152,7 +152,7 @@ func main() { NAT: true, UserAgent: *userAgent, DialTimeout: time.Minute, - MuxerType: p2p.MuxerType(*muxerType), + Muxer: *muxer, NoRelay: *noRelay, }) if err != nil { diff --git a/cmd/harmony/config_migrations.go b/cmd/harmony/config_migrations.go index 20b6be42c6..c8a59c722d 100644 --- a/cmd/harmony/config_migrations.go +++ b/cmd/harmony/config_migrations.go @@ -429,8 +429,8 @@ func init() { if confTree.Get("P2P.DialTimeout") == nil { confTree.Set("P2P.DialTimeout", defaultConfig.P2P.DialTimeout) } - if confTree.Get("P2P.MuxerType") == nil { - confTree.Set("P2P.MuxerType", defaultConfig.P2P.MuxerType) + if confTree.Get("P2P.Muxer") == nil { + confTree.Set("P2P.Muxer", defaultConfig.P2P.Muxer) } if confTree.Get("P2P.NoRelay") == nil { confTree.Set("P2P.NoRelay", defaultConfig.P2P.NoRelay) diff --git a/cmd/harmony/default.go b/cmd/harmony/default.go index 0bff21b35d..f4c64a4d7f 100644 --- a/cmd/harmony/default.go +++ b/cmd/harmony/default.go @@ -43,7 +43,7 @@ var defaultConfig = harmonyconfig.HarmonyConfig{ NAT: nodeconfig.DefaultNAT, UserAgent: nodeconfig.DefaultUserAgent, DialTimeout: nodeconfig.DefaultDialTimeout, - MuxerType: nodeconfig.DefaultMuxerType, + Muxer: nodeconfig.DefaultMuxer, NoRelay: nodeconfig.DefaultNoRelay, }, HTTP: harmonyconfig.HttpConfig{ diff --git a/cmd/harmony/flags.go b/cmd/harmony/flags.go index 18c494243d..255520b356 100644 --- a/cmd/harmony/flags.go +++ b/cmd/harmony/flags.go @@ -69,7 +69,7 @@ var ( noTransportSecurityFlag, natFlag, userAgentFlag, - muxerTypeFlag, + muxerFlag, noRelayFlag, } @@ -657,10 +657,10 @@ var ( Usage: "explicitly set the user-agent, so we can differentiate from other Go libp2p users", DefValue: defaultConfig.P2P.UserAgent, } - muxerTypeFlag = cli.IntFlag{ + muxerFlag = cli.StringFlag{ Name: "p2p.muxer", - Usage: "protocol muxer to mux per-protocol streams (0:Mplex, 1:Yamux, default:0)", - DefValue: defaultConfig.P2P.MuxerType, + Usage: "protocol muxer to mux per-protocol streams, should be comma separated string (mplex, yamux)", + DefValue: defaultConfig.P2P.Muxer, } noRelayFlag = cli.BoolFlag{ Name: "p2p.no-relay", @@ -731,8 +731,8 @@ func applyP2PFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { config.P2P.UserAgent = cli.GetStringFlagValue(cmd, userAgentFlag) } - if cli.IsFlagChanged(cmd, muxerTypeFlag) { - config.P2P.MuxerType = cli.GetIntFlagValue(cmd, muxerTypeFlag) + if cli.IsFlagChanged(cmd, muxerFlag) { + config.P2P.Muxer = cli.GetStringFlagValue(cmd, muxerFlag) } if cli.IsFlagChanged(cmd, noRelayFlag) { diff --git a/cmd/harmony/flags_test.go b/cmd/harmony/flags_test.go index 53971fc1d2..980ddbafd9 100644 --- a/cmd/harmony/flags_test.go +++ b/cmd/harmony/flags_test.go @@ -74,7 +74,7 @@ func TestHarmonyFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, HTTP: harmonyconfig.HttpConfig{ @@ -420,7 +420,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -440,7 +440,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -461,7 +461,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -482,7 +482,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -503,7 +503,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -524,7 +524,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -545,7 +545,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -566,7 +566,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -587,7 +587,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -608,7 +608,7 @@ func TestP2PFlags(t *testing.T) { NAT: false, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -629,12 +629,12 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: "test1", DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: defaultConfig.P2P.NoRelay, }, }, { - args: []string{"--p2p.muxer", "1"}, + args: []string{"--p2p.muxer", "mplex"}, expConfig: harmonyconfig.P2pConfig{ Port: nodeconfig.DefaultP2PPort, IP: nodeconfig.DefaultPublicListenIP, @@ -650,7 +650,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: 1, + Muxer: "mplex", NoRelay: defaultConfig.P2P.NoRelay, }, }, @@ -671,7 +671,7 @@ func TestP2PFlags(t *testing.T) { NAT: defaultConfig.P2P.NAT, UserAgent: defaultConfig.P2P.UserAgent, DialTimeout: defaultConfig.P2P.DialTimeout, - MuxerType: defaultConfig.P2P.MuxerType, + Muxer: defaultConfig.P2P.Muxer, NoRelay: false, }, }, diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index 104cfb700b..b8d6eb6832 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -705,7 +705,7 @@ func createGlobalConfig(hc harmonyconfig.HarmonyConfig) (*nodeconfig.ConfigType, NAT: hc.P2P.NAT, UserAgent: hc.P2P.UserAgent, DialTimeout: hc.P2P.DialTimeout, - MuxerType: p2p.MuxerType(hc.P2P.MuxerType), + Muxer: hc.P2P.Muxer, NoRelay: hc.P2P.NoRelay, }) if err != nil { diff --git a/internal/configs/harmony/harmony.go b/internal/configs/harmony/harmony.go index 719fa48ffe..4fa58acdd8 100644 --- a/internal/configs/harmony/harmony.go +++ b/internal/configs/harmony/harmony.go @@ -133,8 +133,8 @@ type P2pConfig struct { UserAgent string // p2p dial timeout DialTimeout time.Duration - // P2P multiplexer type (default:Mplex, 0:Mplex, 1:Yamux) - MuxerType int + // P2P multiplexer type, should be comma separated (mplex, Yamux) + Muxer string // No relay services, direct connections between peers only NoRelay bool } diff --git a/internal/configs/node/network.go b/internal/configs/node/network.go index cef4d838e4..b43257ead3 100644 --- a/internal/configs/node/network.go +++ b/internal/configs/node/network.go @@ -87,8 +87,8 @@ const ( DefaultUserAgent = "" // DefaultDialTimeout dial timeout DefaultDialTimeout = time.Minute - // DefaultMuxerType P2P multiplexer type (default:Mplex, 0:Mplex, 1:Yamux) - DefaultMuxerType = 0 // 0:Mplex 1:Yamux + // DefaultMuxerType P2P multiplexer type + DefaultMuxer = "mplex, yamux" // DefaultNoRelay disables p2p host relay DefaultNoRelay = true ) diff --git a/p2p/host.go b/p2p/host.go index db75efbf1d..258942d6c7 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -91,14 +91,6 @@ const ( MaxMessageSize = 1 << 21 ) -// Host Multiplexer's Type -type MuxerType int - -const ( - Mplex MuxerType = iota - Yamux -) - // HostConfig is the config structure to create a new host type HostConfig struct { Self *Peer @@ -117,7 +109,7 @@ type HostConfig struct { NAT bool UserAgent string DialTimeout time.Duration - MuxerType MuxerType + Muxer string NoRelay bool } @@ -184,7 +176,6 @@ func NewHost(cfg HostConfig) (Host, error) { } // prepare host options - var idht *dht.IpfsDHT p2pHostConfig := []libp2p.Option{ libp2p.Identity(key), // Explicitly set the user-agent, so we can differentiate from other Go libp2p users. @@ -225,17 +216,23 @@ func NewHost(cfg HostConfig) (Host, error) { p2pHostConfig = append(p2pHostConfig, NoiseC(), TlsC()) } - // Set Muxer (default: Mplex) - switch cfg.MuxerType { - case Yamux: - p2pHostConfig = append(p2pHostConfig, YamuxC()) - case Mplex: - p2pHostConfig = append(p2pHostConfig, MplexC()) - default: - utils.Logger().Error(). - Interface("muxer", cfg.MuxerType). - Msg("Muxer type is invalid, it is set on default value (mplex)") - p2pHostConfig = append(p2pHostConfig, MplexC()) + // Set Muxer + if cfg.Muxer != "" { + for _, v := range strings.Split(cfg.Muxer, ",") { + v = strings.ToLower(strings.TrimSpace(v)) + switch v { + case "yamux": + p2pHostConfig = append(p2pHostConfig, YamuxC()) + case "mplex": + p2pHostConfig = append(p2pHostConfig, MplexC()) + default: + cancel() + utils.Logger().Error(). + Str("muxer", v). + Msg("Muxer type is invalid") + return nil, fmt.Errorf("could not recognize mux %s", v) + } + } } if cfg.ForceReachabilityPublic { From 434abca415e0142bed8e886e92517c9a988b567f Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:28:39 -0400 Subject: [PATCH 27/66] Fix possible panic when the leader is unknown. (#4684) --- consensus/consensus_service.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index 89276c4540..e92e242765 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -484,6 +484,9 @@ func (consensus *Consensus) IsLeader() bool { // isLeader check if the node is a leader or not by comparing the public key of // the node with the leader public key. This function assume it runs under lock. func (consensus *Consensus) isLeader() bool { + if consensus.LeaderPubKey == nil { + return false + } obj := consensus.LeaderPubKey.Object for _, key := range consensus.priKey { if key.Pub.Object.IsEqual(obj) { From b194d2b7c8652087393f4f2b72321b36a4150484 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Fri, 14 Jun 2024 00:38:23 -0400 Subject: [PATCH 28/66] Devnet TopMaxRateEpoch 1976 --- internal/params/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/params/config.go b/internal/params/config.go index e7548c3588..e2a49bdbb6 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -75,7 +75,7 @@ var ( ValidatorCodeFixEpoch: big.NewInt(1535), // 2023-07-20 05:51:07+00:00 HIP30Epoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00 BlockGas30MEpoch: big.NewInt(1673), // 2023-11-02 17:30:00+00:00 - TopMaxRateEpoch: EpochTBD, + TopMaxRateEpoch: big.NewInt(1976), // around 2024-06-20 00:06:05 UTC MaxRateEpoch: big.NewInt(1733), // 2023-12-17 12:20:15+00:00 DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, From ef745011bf2f41143ef1b038a9d53eef9938a365 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Fri, 14 Jun 2024 00:53:10 -0400 Subject: [PATCH 29/66] Fixed order --- internal/params/config.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/params/config.go b/internal/params/config.go index e2a49bdbb6..61b1ae23fc 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -169,8 +169,8 @@ var ( ValidatorCodeFixEpoch: EpochTBD, HIP30Epoch: EpochTBD, BlockGas30MEpoch: big.NewInt(0), - MaxRateEpoch: EpochTBD, TopMaxRateEpoch: EpochTBD, + MaxRateEpoch: EpochTBD, DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, } @@ -217,6 +217,7 @@ var ( ValidatorCodeFixEpoch: big.NewInt(5), HIP30Epoch: big.NewInt(7), BlockGas30MEpoch: big.NewInt(7), + TopMaxRateEpoch: EpochTBD, MaxRateEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, DevnetExternalEpoch: big.NewInt(144), @@ -311,8 +312,8 @@ var ( ValidatorCodeFixEpoch: big.NewInt(2), HIP30Epoch: EpochTBD, BlockGas30MEpoch: big.NewInt(0), - MaxRateEpoch: EpochTBD, TopMaxRateEpoch: EpochTBD, + MaxRateEpoch: EpochTBD, DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, } From d748647f2dbef40354905a5854b27ba85b9e94a7 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Mon, 24 Jun 2024 23:34:49 -0400 Subject: [PATCH 30/66] Configurable reward frequency. (#4700) --- internal/chain/reward.go | 6 ++---- internal/configs/sharding/fixedschedule.go | 5 +++++ internal/configs/sharding/localnet.go | 9 +++++++-- internal/configs/sharding/mainnet.go | 5 +++++ internal/configs/sharding/pangaea.go | 5 +++++ internal/configs/sharding/partner.go | 5 +++++ internal/configs/sharding/shardingconfig.go | 8 ++++++++ internal/configs/sharding/stress.go | 5 +++++ internal/configs/sharding/testnet.go | 5 +++++ 9 files changed, 47 insertions(+), 6 deletions(-) diff --git a/internal/chain/reward.go b/internal/chain/reward.go index 42212d6db2..1cfd1ea0af 100644 --- a/internal/chain/reward.go +++ b/internal/chain/reward.go @@ -33,8 +33,6 @@ import ( const ( // AsyncBlockProposalTimeout is the timeout which will abort the async block proposal. AsyncBlockProposalTimeout = 9 * time.Second - // RewardFrequency the number of blocks between each aggregated reward distribution - RewardFrequency = 64 ) type slotPayable struct { @@ -281,7 +279,7 @@ func AccumulateRewardsAndCountSigs( } // Only do reward distribution at the 63th block in the modulus. - if blockNum%RewardFrequency != RewardFrequency-1 { + if blockNum%shard.Schedule.RewardFrequency() != shard.Schedule.RewardFrequency()-1 { return numeric.ZeroDec(), network.EmptyPayout, nil } @@ -322,7 +320,7 @@ func distributeRewardAfterAggregateEpoch(bc engine.ChainReader, state *state.DB, startTime := time.Now() // loop through [0...63] position in the modulus index of the 64 blocks // Note the current block is at position 63 of the modulus. - for i := curBlockNum - RewardFrequency + 1; i <= curBlockNum; i++ { + for i := curBlockNum - shard.Schedule.RewardFrequency() + 1; i <= curBlockNum; i++ { if i < 0 { continue } diff --git a/internal/configs/sharding/fixedschedule.go b/internal/configs/sharding/fixedschedule.go index 1576f9321a..b89dde449d 100644 --- a/internal/configs/sharding/fixedschedule.go +++ b/internal/configs/sharding/fixedschedule.go @@ -60,3 +60,8 @@ func (s fixedSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool { func NewFixedSchedule(instance Instance) Schedule { return fixedSchedule{instance: instance} } + +// RewardFrequency returns the frequency of block reward +func (s fixedSchedule) RewardFrequency() uint64 { + return RewardFrequency +} diff --git a/internal/configs/sharding/localnet.go b/internal/configs/sharding/localnet.go index fb6050b1de..60d2876fdd 100644 --- a/internal/configs/sharding/localnet.go +++ b/internal/configs/sharding/localnet.go @@ -31,8 +31,8 @@ const ( localnetV1Epoch = 1 localnetEpochBlock1 = 5 - localnetBlocksPerEpoch = 64 - localnetBlocksPerEpochV2 = 64 + localnetBlocksPerEpoch = 16 + localnetBlocksPerEpochV2 = 16 localnetVdfDifficulty = 5000 // This takes about 10s to finish the vdf ) @@ -157,6 +157,11 @@ func (ls localnetSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool { return false } +// RewardFrequency returns the frequency of block reward +func (ls localnetSchedule) RewardFrequency() uint64 { + return 16 +} + var ( localnetReshardingEpoch = []*big.Int{ big.NewInt(0), big.NewInt(localnetV1Epoch), params.LocalnetChainConfig.StakingEpoch, params.LocalnetChainConfig.TwoSecondsEpoch, diff --git a/internal/configs/sharding/mainnet.go b/internal/configs/sharding/mainnet.go index 2106b58d8c..e237b85e97 100644 --- a/internal/configs/sharding/mainnet.go +++ b/internal/configs/sharding/mainnet.go @@ -225,6 +225,11 @@ func (ms mainnetSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool { return false } +// RewardFrequency returns the frequency of block reward +func (ms mainnetSchedule) RewardFrequency() uint64 { + return RewardFrequency +} + var mainnetReshardingEpoch = []*big.Int{big.NewInt(0), big.NewInt(mainnetV0_1Epoch), big.NewInt(mainnetV0_2Epoch), big.NewInt(mainnetV0_3Epoch), big.NewInt(mainnetV0_4Epoch), big.NewInt(mainnetV1Epoch), big.NewInt(mainnetV1_1Epoch), big.NewInt(mainnetV1_2Epoch), big.NewInt(mainnetV1_3Epoch), big.NewInt(mainnetV1_4Epoch), big.NewInt(mainnetV1_5Epoch), big.NewInt(mainnetV2_0Epoch), big.NewInt(mainnetV2_1Epoch), big.NewInt(mainnetV2_2Epoch), params.MainnetChainConfig.TwoSecondsEpoch, params.MainnetChainConfig.SixtyPercentEpoch, params.MainnetChainConfig.HIP6And8Epoch} var ( diff --git a/internal/configs/sharding/pangaea.go b/internal/configs/sharding/pangaea.go index 46e87b1042..56cb5f53c0 100644 --- a/internal/configs/sharding/pangaea.go +++ b/internal/configs/sharding/pangaea.go @@ -71,6 +71,11 @@ func (ps pangaeaSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool { return false } +// RewardFrequency returns the frequency of block reward +func (ps pangaeaSchedule) RewardFrequency() uint64 { + return RewardFrequency +} + var pangaeaReshardingEpoch = []*big.Int{ big.NewInt(0), params.PangaeaChainConfig.StakingEpoch, diff --git a/internal/configs/sharding/partner.go b/internal/configs/sharding/partner.go index 7fb9743ab6..9f2332cc6e 100644 --- a/internal/configs/sharding/partner.go +++ b/internal/configs/sharding/partner.go @@ -88,6 +88,11 @@ func (ps partnerSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool { return false } +// RewardFrequency returns the frequency of block reward +func (ps partnerSchedule) RewardFrequency() uint64 { + return RewardFrequency +} + var partnerReshardingEpoch = []*big.Int{ big.NewInt(0), params.PartnerChainConfig.StakingEpoch, diff --git a/internal/configs/sharding/shardingconfig.go b/internal/configs/sharding/shardingconfig.go index 740e83ffb4..6ac05e7b98 100644 --- a/internal/configs/sharding/shardingconfig.go +++ b/internal/configs/sharding/shardingconfig.go @@ -13,6 +13,11 @@ import ( "github.com/harmony-one/harmony/internal/genesis" ) +const ( + // RewardFrequency the number of blocks between each aggregated reward distribution + RewardFrequency = 64 +) + // Schedule returns the sharding configuration instance for the given // epoch. type Schedule interface { @@ -40,6 +45,9 @@ type Schedule interface { // IsSkippedEpoch returns if epoch was skipped on shard chain IsSkippedEpoch(uint32, *big.Int) bool + + // RewardFrequency returns the frequency of block reward + RewardFrequency() uint64 } // Instance is one sharding configuration instance. diff --git a/internal/configs/sharding/stress.go b/internal/configs/sharding/stress.go index eadd07d74a..dcd38e1181 100644 --- a/internal/configs/sharding/stress.go +++ b/internal/configs/sharding/stress.go @@ -74,6 +74,11 @@ func (ss stressnetSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool return false } +// RewardFrequency returns the frequency of block reward +func (ss stressnetSchedule) RewardFrequency() uint64 { + return RewardFrequency +} + var stressnetReshardingEpoch = []*big.Int{ big.NewInt(0), params.StressnetChainConfig.StakingEpoch, diff --git a/internal/configs/sharding/testnet.go b/internal/configs/sharding/testnet.go index 6a957ec820..b0ada0f5bc 100644 --- a/internal/configs/sharding/testnet.go +++ b/internal/configs/sharding/testnet.go @@ -125,6 +125,11 @@ func (ts testnetSchedule) IsSkippedEpoch(shardID uint32, epoch *big.Int) bool { return false } +// RewardFrequency returns the frequency of block reward +func (ts testnetSchedule) RewardFrequency() uint64 { + return RewardFrequency +} + var testnetReshardingEpoch = []*big.Int{ big.NewInt(0), params.TestnetChainConfig.StakingEpoch, From d6da9ffab5c0f5a8721c59cc629110b5d016e566 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Tue, 25 Jun 2024 01:40:36 -0400 Subject: [PATCH 31/66] Block proposing moved from Node to Consensus. (#4698) --- api/service/blockproposal/service.go | 20 +- consensus/consensus.go | 6 +- consensus/consensus_block_proposing.go | 492 +++++++++++++++++++++++++ consensus/consensus_v2.go | 9 +- internal/registry/registry.go | 19 + internal/utils/utils.go | 13 +- node/api.go | 8 +- node/node.go | 76 +--- node/node_newblock.go | 413 --------------------- node/service_setup.go | 2 +- node/worker/types.go | 10 +- node/worker/worker.go | 11 +- 12 files changed, 561 insertions(+), 518 deletions(-) create mode 100644 consensus/consensus_block_proposing.go diff --git a/api/service/blockproposal/service.go b/api/service/blockproposal/service.go index 82db7c63a7..a1bc397d96 100644 --- a/api/service/blockproposal/service.go +++ b/api/service/blockproposal/service.go @@ -8,20 +8,18 @@ import ( // Service is a block proposal service. type Service struct { - stopChan chan struct{} - stoppedChan chan struct{} - c *consensus.Consensus - messageChan chan *msg_pb.Message - waitForConsensusReady func(c *consensus.Consensus, stopChan chan struct{}, stoppedChan chan struct{}) + stopChan chan struct{} + stoppedChan chan struct{} + c *consensus.Consensus + messageChan chan *msg_pb.Message } // New returns a block proposal service. -func New(c *consensus.Consensus, waitForConsensusReady func(c *consensus.Consensus, stopChan chan struct{}, stoppedChan chan struct{})) *Service { +func New(c *consensus.Consensus) *Service { return &Service{ - c: c, - waitForConsensusReady: waitForConsensusReady, - stopChan: make(chan struct{}), - stoppedChan: make(chan struct{}), + c: c, + stopChan: make(chan struct{}), + stoppedChan: make(chan struct{}), } } @@ -32,7 +30,7 @@ func (s *Service) Start() error { } func (s *Service) run() { - s.waitForConsensusReady(s.c, s.stopChan, s.stoppedChan) + s.c.WaitForConsensusReadyV2(s.stopChan, s.stoppedChan) } // Stop stops block proposal service. diff --git a/consensus/consensus.go b/consensus/consensus.go index 4440fe9780..d9f96b94fa 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -75,6 +75,7 @@ type Consensus struct { multiSigBitmap *bls_cosi.Mask // Bitmap for parsing multisig bitmap from validators + pendingCXReceipts map[utils.CXKey]*types.CXReceiptsProof // All the receipts received but not yet processed for Consensus // Registry for services. registry *registry.Registry // Minimal number of peers in the shard @@ -296,8 +297,9 @@ func New( host: host, msgSender: NewMessageSender(host), // FBFT timeout - consensusTimeout: createTimeout(), - dHelper: downloadAsync{}, + consensusTimeout: createTimeout(), + dHelper: downloadAsync{}, + pendingCXReceipts: make(map[utils.CXKey]*types.CXReceiptsProof), // All the receipts received but not yet processed for Consensus } if multiBLSPriKey != nil { diff --git a/consensus/consensus_block_proposing.go b/consensus/consensus_block_proposing.go new file mode 100644 index 0000000000..aeb892aaeb --- /dev/null +++ b/consensus/consensus_block_proposing.go @@ -0,0 +1,492 @@ +package consensus + +import ( + "sort" + "strings" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/harmony-one/harmony/core" + "github.com/harmony-one/harmony/core/rawdb" + "github.com/harmony-one/harmony/core/types" + "github.com/harmony-one/harmony/crypto/bls" + "github.com/harmony-one/harmony/internal/utils" + "github.com/harmony-one/harmony/node/worker" + "github.com/harmony-one/harmony/shard" + staking "github.com/harmony-one/harmony/staking/types" + "github.com/pkg/errors" +) + +// Constants of proposing a new block +const ( + IncomingReceiptsLimit = 6000 // 2000 * (numShards - 1) + SleepPeriod = 20 * time.Millisecond +) + +// ProposeNewBlock proposes a new block... +func (consensus *Consensus) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error) { + var ( + currentHeader = consensus.Blockchain().CurrentHeader() + nowEpoch = currentHeader.Epoch() + blockNow = currentHeader.Number() + worker = consensus.registry.GetWorker() + ) + utils.AnalysisStart("ProposeNewBlock", nowEpoch, blockNow) + defer utils.AnalysisEnd("ProposeNewBlock", nowEpoch, blockNow) + + // Update worker's current header and + // state data in preparation to propose/process new transactions + env, err := worker.UpdateCurrent() + if err != nil { + return nil, errors.Wrap(err, "failed to update worker") + } + header := env.CurrentHeader() + shardState, err := consensus.Blockchain().ReadShardState(header.Epoch()) + if err != nil { + return nil, errors.WithMessage(err, "failed to read shard") + } + + var ( + leaderKey = consensus.GetLeaderPubKey() + coinbase = consensus.registry.GetAddressToBLSKey().GetAddressForBLSKey(consensus.GetPublicKeys(), shardState, leaderKey.Object, header.Epoch()) + beneficiary = coinbase + ) + + // After staking, all coinbase will be the address of bls pub key + if consensus.Blockchain().Config().IsStaking(header.Epoch()) { + blsPubKeyBytes := leaderKey.Object.GetAddress() + coinbase.SetBytes(blsPubKeyBytes[:]) + } + + if coinbase == (common.Address{}) { + return nil, errors.New("[ProposeNewBlock] Failed setting coinbase") + } + + // Must set coinbase here because the operations below depend on it + header.SetCoinbase(coinbase) + + // Get beneficiary based on coinbase + // Before staking, coinbase itself is the beneficial + // After staking, beneficial is the corresponding ECDSA address of the bls key + beneficiary, err = consensus.Blockchain().GetECDSAFromCoinbase(header) + if err != nil { + return nil, err + } + + // Add VRF + if consensus.Blockchain().Config().IsVRF(header.Epoch()) { + //generate a new VRF for the current block + if err := consensus.GenerateVrfAndProof(header); err != nil { + return nil, err + } + } + + // Execute all the time except for last block of epoch for shard 0 + if !shard.Schedule.IsLastBlock(header.Number().Uint64()) || consensus.ShardID != 0 { + // Prepare normal and staking transactions retrieved from transaction pool + utils.AnalysisStart("proposeNewBlockChooseFromTxnPool") + + pendingPoolTxs, err := consensus.registry.GetTxPool().Pending() + if err != nil { + utils.Logger().Err(err).Msg("Failed to fetch pending transactions") + return nil, err + } + pendingPlainTxs := map[common.Address]types.Transactions{} + pendingStakingTxs := staking.StakingTransactions{} + for addr, poolTxs := range pendingPoolTxs { + plainTxsPerAcc := types.Transactions{} + for _, tx := range poolTxs { + if plainTx, ok := tx.(*types.Transaction); ok { + plainTxsPerAcc = append(plainTxsPerAcc, plainTx) + } else if stakingTx, ok := tx.(*staking.StakingTransaction); ok { + // Only process staking transactions after pre-staking epoch happened. + if consensus.Blockchain().Config().IsPreStaking(worker.GetCurrentHeader().Epoch()) { + pendingStakingTxs = append(pendingStakingTxs, stakingTx) + } + } else { + utils.Logger().Err(types.ErrUnknownPoolTxType). + Msg("Failed to parse pending transactions") + return nil, types.ErrUnknownPoolTxType + } + } + if plainTxsPerAcc.Len() > 0 { + pendingPlainTxs[addr] = plainTxsPerAcc + } + } + + // Try commit normal and staking transactions based on the current state + // The successfully committed transactions will be put in the proposed block + if err := worker.CommitTransactions( + pendingPlainTxs, pendingStakingTxs, beneficiary, + ); err != nil { + utils.Logger().Error().Err(err).Msg("cannot commit transactions") + return nil, err + } + utils.AnalysisEnd("proposeNewBlockChooseFromTxnPool") + } + + // Prepare incoming cross shard transaction receipts + // These are accepted even during the epoch before hip-30 + // because the destination shard only receives them after + // balance is deducted on source shard. to prevent this from + // being a significant problem, the source shards will stop + // accepting txs destined to the shards which are shutting down + // one epoch prior the shut down + receiptsList := consensus.proposeReceiptsProof() + + if len(receiptsList) != 0 { + if err := worker.CommitReceipts(receiptsList); err != nil { + return nil, err + } + } + + isBeaconchainInCrossLinkEra := consensus.ShardID == shard.BeaconChainShardID && + consensus.Blockchain().Config().IsCrossLink(worker.GetCurrentHeader().Epoch()) + + isBeaconchainInStakingEra := consensus.ShardID == shard.BeaconChainShardID && + consensus.Blockchain().Config().IsStaking(worker.GetCurrentHeader().Epoch()) + + utils.AnalysisStart("proposeNewBlockVerifyCrossLinks") + // Prepare cross links and slashing messages + var crossLinksToPropose types.CrossLinks + if isBeaconchainInCrossLinkEra { + allPending, err := consensus.Blockchain().ReadPendingCrossLinks() + invalidToDelete := []types.CrossLink{} + if err == nil { + for _, pending := range allPending { + // ReadCrossLink beacon chain usage. + exist, err := consensus.Blockchain().ReadCrossLink(pending.ShardID(), pending.BlockNum()) + if err == nil || exist != nil { + invalidToDelete = append(invalidToDelete, pending) + utils.Logger().Debug(). + AnErr("[ProposeNewBlock] pending crosslink is already committed onchain", err) + continue + } + last, err := consensus.Blockchain().ReadShardLastCrossLink(pending.ShardID()) + if err != nil { + utils.Logger().Debug(). + AnErr("[ProposeNewBlock] failed to read last crosslink", err) + // no return + } + // if pending crosslink is older than the last crosslink, delete it and continue + if err == nil && exist == nil && last != nil && last.BlockNum() >= pending.BlockNum() { + invalidToDelete = append(invalidToDelete, pending) + } + + // Crosslink is already verified before it's accepted to pending, + // no need to verify again in proposal. + if !consensus.Blockchain().Config().IsCrossLink(pending.Epoch()) { + utils.Logger().Debug(). + AnErr("[ProposeNewBlock] pending crosslink that's before crosslink epoch", err) + continue + } + + crossLinksToPropose = append(crossLinksToPropose, pending) + if len(crossLinksToPropose) > 15 { + break + } + } + utils.Logger().Info(). + Msgf("[ProposeNewBlock] Proposed %d crosslinks from %d pending crosslinks", + len(crossLinksToPropose), len(allPending), + ) + } else { + utils.Logger().Warn().Err(err).Msgf( + "[ProposeNewBlock] Unable to Read PendingCrossLinks, number of crosslinks: %d", + len(allPending), + ) + } + if n, err := consensus.Blockchain().DeleteFromPendingCrossLinks(invalidToDelete); err != nil { + utils.Logger().Error(). + Err(err). + Msg("[ProposeNewBlock] invalid pending cross links failed") + } else if len(invalidToDelete) > 0 { + utils.Logger().Info(). + Int("not-deleted", n). + Int("deleted", len(invalidToDelete)). + Msg("[ProposeNewBlock] deleted invalid pending cross links") + } + } + utils.AnalysisEnd("proposeNewBlockVerifyCrossLinks") + + if isBeaconchainInStakingEra { + // this will set a meaningful w.current.slashes + if err := worker.CollectVerifiedSlashes(); err != nil { + return nil, err + } + } + + worker.ApplyShardReduction() + + // Prepare shard state + if shardState, err = consensus.Blockchain().SuperCommitteeForNextEpoch( + consensus.Beaconchain(), worker.GetCurrentHeader(), false, + ); err != nil { + return nil, err + } + + viewIDFunc := func() uint64 { + return consensus.GetCurBlockViewID() + } + finalizedBlock, err := worker.FinalizeNewBlock( + commitSigs, viewIDFunc, + coinbase, crossLinksToPropose, shardState, + ) + if err != nil { + utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Failed finalizing the new block") + return nil, err + } + + utils.Logger().Info().Msg("[ProposeNewBlock] verifying the new block header") + err = core.NewBlockValidator(consensus.Blockchain()).ValidateHeader(finalizedBlock, true) + + if err != nil { + utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Failed verifying the new block header") + return nil, err + } + + // Save process result in the cache for later use for faster block commitment to db. + result := worker.GetCurrentResult() + consensus.Blockchain().Processor().CacheProcessorResult(finalizedBlock.Hash(), result) + return finalizedBlock, nil +} + +func (consensus *Consensus) proposeReceiptsProof() []*types.CXReceiptsProof { + if !consensus.Blockchain().Config().HasCrossTxFields(consensus.registry.GetWorker().GetCurrentHeader().Epoch()) { + return []*types.CXReceiptsProof{} + } + + numProposed := 0 + validReceiptsList := []*types.CXReceiptsProof{} + pendingReceiptsList := []*types.CXReceiptsProof{} + + // not necessary to sort the list, but we just prefer to process the list ordered by shard and blocknum + pendingCXReceipts := []*types.CXReceiptsProof{} + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + for _, v := range consensus.pendingCXReceipts { + pendingCXReceipts = append(pendingCXReceipts, v) + } + + sort.SliceStable(pendingCXReceipts, func(i, j int) bool { + shardCMP := pendingCXReceipts[i].MerkleProof.ShardID < pendingCXReceipts[j].MerkleProof.ShardID + shardEQ := pendingCXReceipts[i].MerkleProof.ShardID == pendingCXReceipts[j].MerkleProof.ShardID + blockCMP := pendingCXReceipts[i].MerkleProof.BlockNum.Cmp( + pendingCXReceipts[j].MerkleProof.BlockNum, + ) == -1 + return shardCMP || (shardEQ && blockCMP) + }) + + m := map[common.Hash]struct{}{} + +Loop: + for _, cxp := range consensus.pendingCXReceipts { + if numProposed > IncomingReceiptsLimit { + pendingReceiptsList = append(pendingReceiptsList, cxp) + continue + } + // check double spent + if consensus.Blockchain().IsSpent(cxp) { + utils.Logger().Debug().Interface("cxp", cxp).Msg("[proposeReceiptsProof] CXReceipt is spent") + continue + } + hash := cxp.MerkleProof.BlockHash + // ignore duplicated receipts + if _, ok := m[hash]; ok { + continue + } else { + m[hash] = struct{}{} + } + + for _, item := range cxp.Receipts { + if item.ToShardID != consensus.Blockchain().ShardID() { + continue Loop + } + } + + if err := core.NewBlockValidator(consensus.Blockchain()).ValidateCXReceiptsProof(cxp); err != nil { + if strings.Contains(err.Error(), rawdb.MsgNoShardStateFromDB) { + pendingReceiptsList = append(pendingReceiptsList, cxp) + } else { + utils.Logger().Error().Err(err).Msg("[proposeReceiptsProof] Invalid CXReceiptsProof") + } + continue + } + + utils.Logger().Debug().Interface("cxp", cxp).Msg("[proposeReceiptsProof] CXReceipts Added") + validReceiptsList = append(validReceiptsList, cxp) + numProposed = numProposed + len(cxp.Receipts) + } + + consensus.pendingCXReceipts = make(map[utils.CXKey]*types.CXReceiptsProof) + for _, v := range pendingReceiptsList { + blockNum := v.Header.Number().Uint64() + shardID := v.Header.ShardID() + key := utils.GetPendingCXKey(shardID, blockNum) + consensus.pendingCXReceipts[key] = v + } + + utils.Logger().Debug().Msgf("[proposeReceiptsProof] number of validReceipts %d", len(validReceiptsList)) + return validReceiptsList +} + +func (consensus *Consensus) AddPendingReceipts(receipts *types.CXReceiptsProof) { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + if receipts.ContainsEmptyField() { + utils.Logger().Info(). + Int("totalPendingReceipts", len(consensus.pendingCXReceipts)). + Msg("CXReceiptsProof contains empty field") + return + } + + blockNum := receipts.Header.Number().Uint64() + shardID := receipts.Header.ShardID() + + // Sanity checks + + if err := core.NewBlockValidator(consensus.Blockchain()).ValidateCXReceiptsProof(receipts); err != nil { + if !strings.Contains(err.Error(), rawdb.MsgNoShardStateFromDB) { + utils.Logger().Error().Err(err).Msg("[AddPendingReceipts] Invalid CXReceiptsProof") + return + } + } + + // cross-shard receipt should not be coming from our shard + if s := consensus.ShardID; s == shardID { + utils.Logger().Info(). + Uint32("my-shard", s). + Uint32("receipt-shard", shardID). + Msg("ShardID of incoming receipt was same as mine") + return + } + + if e := receipts.Header.Epoch(); blockNum == 0 || + !consensus.Blockchain().Config().AcceptsCrossTx(e) { + utils.Logger().Info(). + Uint64("incoming-epoch", e.Uint64()). + Msg("Incoming receipt had meaningless epoch") + return + } + + key := utils.GetPendingCXKey(shardID, blockNum) + + // DDoS protection + const maxCrossTxnSize = 4096 + if s := len(consensus.pendingCXReceipts); s >= maxCrossTxnSize { + utils.Logger().Info(). + Int("pending-cx-receipts-size", s). + Int("pending-cx-receipts-limit", maxCrossTxnSize). + Msg("Current pending cx-receipts reached size limit") + return + } + + if _, ok := consensus.pendingCXReceipts[key]; ok { + utils.Logger().Info(). + Int("totalPendingReceipts", len(consensus.pendingCXReceipts)). + Msg("Already Got Same Receipt message") + return + } + consensus.pendingCXReceipts[key] = receipts + utils.Logger().Info(). + Int("totalPendingReceipts", len(consensus.pendingCXReceipts)). + Msg("Got ONE more receipt message") +} + +// PendingCXReceipts returns node.pendingCXReceiptsProof +func (consensus *Consensus) PendingCXReceipts() []*types.CXReceiptsProof { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + cxReceipts := make([]*types.CXReceiptsProof, len(consensus.pendingCXReceipts)) + i := 0 + for _, cxReceipt := range consensus.pendingCXReceipts { + cxReceipts[i] = cxReceipt + i++ + } + return cxReceipts +} + +// WaitForConsensusReadyV2 listen for the readiness signal from consensus and generate new block for consensus. +// only leader will receive the ready signal +func (consensus *Consensus) WaitForConsensusReadyV2(stopChan chan struct{}, stoppedChan chan struct{}) { + go func() { + // Setup stoppedChan + defer close(stoppedChan) + + utils.Logger().Debug(). + Msg("Waiting for Consensus ready") + select { + case <-time.After(30 * time.Second): + case <-stopChan: + return + } + + for { + // keep waiting for Consensus ready + select { + case <-stopChan: + utils.Logger().Warn(). + Msg("Consensus new block proposal: STOPPED!") + return + case proposal := <-consensus.GetReadySignal(): + for retryCount := 0; retryCount < 3 && consensus.IsLeader(); retryCount++ { + time.Sleep(SleepPeriod) + utils.Logger().Info(). + Uint64("blockNum", consensus.Blockchain().CurrentBlock().NumberU64()+1). + Bool("asyncProposal", proposal.Type == AsyncProposal). + Str("called", proposal.Caller). + Msg("PROPOSING NEW BLOCK ------------------------------------------------") + + // Prepare last commit signatures + newCommitSigsChan := make(chan []byte) + + go func() { + waitTime := 0 * time.Second + if proposal.Type == AsyncProposal { + waitTime = worker.CommitSigReceiverTimeout + } + select { + case <-time.After(waitTime): + if waitTime == 0 { + utils.Logger().Info().Msg("[ProposeNewBlock] Sync block proposal, reading commit sigs directly from DB") + } else { + utils.Logger().Info().Msg("[ProposeNewBlock] Timeout waiting for commit sigs, reading directly from DB") + } + sigs, err := consensus.BlockCommitSigs(consensus.Blockchain().CurrentBlock().NumberU64()) + + if err != nil { + utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Cannot get commit signatures from last block") + } else { + newCommitSigsChan <- sigs + } + case commitSigs := <-consensus.GetCommitSigChannel(): + utils.Logger().Info().Msg("[ProposeNewBlock] received commit sigs asynchronously") + if len(commitSigs) > bls.BLSSignatureSizeInBytes { + newCommitSigsChan <- commitSigs + } + } + }() + newBlock, err := consensus.ProposeNewBlock(newCommitSigsChan) + if err == nil { + utils.Logger().Info(). + Uint64("blockNum", newBlock.NumberU64()). + Uint64("epoch", newBlock.Epoch().Uint64()). + Uint64("viewID", newBlock.Header().ViewID().Uint64()). + Int("numTxs", newBlock.Transactions().Len()). + Int("numStakingTxs", newBlock.StakingTransactions().Len()). + Int("crossShardReceipts", newBlock.IncomingReceipts().Len()). + Msgf("=========Successfully Proposed New Block, shard: %d epoch: %d number: %d ==========", newBlock.ShardID(), newBlock.Epoch().Uint64(), newBlock.NumberU64()) + + // Send the new block to Consensus so it can be confirmed. + consensus.BlockChannel(newBlock) + break + } else { + utils.Logger().Err(err).Int("retryCount", retryCount). + Msg("!!!!!!!!!Failed Proposing New Block!!!!!!!!!") + continue + } + } + } + } + }() +} diff --git a/consensus/consensus_v2.go b/consensus/consensus_v2.go index 822d239001..6caed6e504 100644 --- a/consensus/consensus_v2.go +++ b/consensus/consensus_v2.go @@ -38,9 +38,6 @@ var ( const ( // CommitSigSenderTimeout is the timeout for sending the commit sig to finish block proposal CommitSigSenderTimeout = 10 * time.Second - // CommitSigReceiverTimeout is the timeout for the receiving side of the commit sig - // if timeout, the receiver should instead ready directly from db for the commit sig - CommitSigReceiverTimeout = 8 * time.Second ) // IsViewChangingMode return true if curernt mode is viewchanging @@ -845,6 +842,12 @@ func (consensus *Consensus) postCatchup(initBN uint64) { // GenerateVrfAndProof generates new VRF/Proof from hash of previous block func (consensus *Consensus) GenerateVrfAndProof(newHeader *block.Header) error { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + return consensus.generateVrfAndProof(newHeader) +} + +func (consensus *Consensus) generateVrfAndProof(newHeader *block.Header) error { key, err := consensus.getConsensusLeaderPrivateKey() if err != nil { return errors.New("[GenerateVrfAndProof] no leader private key provided") diff --git a/internal/registry/registry.go b/internal/registry/registry.go index cb5729e926..760bb8d381 100644 --- a/internal/registry/registry.go +++ b/internal/registry/registry.go @@ -11,6 +11,7 @@ import ( 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/node/worker" "github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/webhooks" ) @@ -28,6 +29,7 @@ type Registry struct { collection *shardchain.CollectionImpl nodeConfig *nodeconfig.ConfigType addressToBLSKey AddressToBLSKey + worker *worker.Worker } // New creates a new registry. @@ -199,6 +201,23 @@ func (r *Registry) SetAddressToBLSKey(a AddressToBLSKey) *Registry { return r } +// SetWorker sets the worker to registry. +func (r *Registry) SetWorker(w *worker.Worker) *Registry { + r.mu.Lock() + defer r.mu.Unlock() + + r.worker = w + return r +} + +// GetWorker gets the worker from registry. +func (r *Registry) GetWorker() *worker.Worker { + r.mu.Lock() + defer r.mu.Unlock() + + return r.worker +} + type FindCommitteeByID interface { FindCommitteeByID(shardID uint32) (*shard.Committee, error) } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index f23b64f51c..28af81aed8 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -235,11 +235,18 @@ func IsPrivateIP(ip net.IP) bool { return false } +type CXKey struct { + shardID uint32 + blockNum uint64 +} + // GetPendingCXKey creates pending CXReceiptsProof key given shardID and blockNum // it is to avoid adding duplicated CXReceiptsProof from the same source shard -func GetPendingCXKey(shardID uint32, blockNum uint64) string { - key := strconv.FormatUint(uint64(shardID), 10) + "-" + strconv.FormatUint(blockNum, 10) - return key +func GetPendingCXKey(shardID uint32, blockNum uint64) CXKey { + return CXKey{ + shardID: shardID, + blockNum: blockNum, + } } // AppendIfMissing appends an item if it's missing in the slice, returns appended slice and true diff --git a/node/api.go b/node/api.go index e3862f510c..d49d40f076 100644 --- a/node/api.go +++ b/node/api.go @@ -42,13 +42,7 @@ func (node *Node) ListBlockedPeer() []peer.ID { // PendingCXReceipts returns node.pendingCXReceiptsProof func (node *Node) PendingCXReceipts() []*types.CXReceiptsProof { - cxReceipts := make([]*types.CXReceiptsProof, len(node.pendingCXReceipts)) - i := 0 - for _, cxReceipt := range node.pendingCXReceipts { - cxReceipts[i] = cxReceipt - i++ - } - return cxReceipts + return node.Consensus.PendingCXReceipts() } // ReportStakingErrorSink is the report of failed staking transactions this node has (held in memory only) diff --git a/node/node.go b/node/node.go index 1b4cb69142..80a18e554a 100644 --- a/node/node.go +++ b/node/node.go @@ -7,7 +7,6 @@ import ( "math/big" "os" "runtime/pprof" - "strings" "sync" "time" @@ -23,7 +22,6 @@ import ( "github.com/harmony-one/harmony/api/service/stagedsync" "github.com/harmony-one/harmony/consensus" "github.com/harmony-one/harmony/core" - "github.com/harmony-one/harmony/core/rawdb" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/crypto/bls" harmonyconfig "github.com/harmony-one/harmony/internal/configs/harmony" @@ -90,11 +88,10 @@ type ISync interface { // Node represents a protocol-participating node in the network type Node struct { - Consensus *consensus.Consensus // Consensus object containing all Consensus related data (e.g. committee members, signatures, commits) - BeaconBlockChannel chan *types.Block // The channel to send beacon blocks for non-beaconchain nodes - pendingCXReceipts map[string]*types.CXReceiptsProof // All the receipts received but not yet processed for Consensus - pendingCXMutex sync.Mutex - crosslinks *crosslinks.Crosslinks // Memory storage for crosslink processing. + Consensus *consensus.Consensus // Consensus object containing all Consensus related data (e.g. committee members, signatures, commits) + BeaconBlockChannel chan *types.Block // The channel to send beacon blocks for non-beaconchain nodes + + crosslinks *crosslinks.Crosslinks // Memory storage for crosslink processing. SelfPeer p2p.Peer stateMutex sync.Mutex // mutex for change node state @@ -363,67 +360,7 @@ func (node *Node) AddPendingTransaction(newTx *types.Transaction) error { // AddPendingReceipts adds one receipt message to pending list. func (node *Node) AddPendingReceipts(receipts *types.CXReceiptsProof) { - node.pendingCXMutex.Lock() - defer node.pendingCXMutex.Unlock() - - if receipts.ContainsEmptyField() { - utils.Logger().Info(). - Int("totalPendingReceipts", len(node.pendingCXReceipts)). - Msg("CXReceiptsProof contains empty field") - return - } - - blockNum := receipts.Header.Number().Uint64() - shardID := receipts.Header.ShardID() - - // Sanity checks - - if err := core.NewBlockValidator(node.Blockchain()).ValidateCXReceiptsProof(receipts); err != nil { - if !strings.Contains(err.Error(), rawdb.MsgNoShardStateFromDB) { - utils.Logger().Error().Err(err).Msg("[AddPendingReceipts] Invalid CXReceiptsProof") - return - } - } - - // cross-shard receipt should not be coming from our shard - if s := node.Consensus.ShardID; s == shardID { - utils.Logger().Info(). - Uint32("my-shard", s). - Uint32("receipt-shard", shardID). - Msg("ShardID of incoming receipt was same as mine") - return - } - - if e := receipts.Header.Epoch(); blockNum == 0 || - !node.Blockchain().Config().AcceptsCrossTx(e) { - utils.Logger().Info(). - Uint64("incoming-epoch", e.Uint64()). - Msg("Incoming receipt had meaningless epoch") - return - } - - key := utils.GetPendingCXKey(shardID, blockNum) - - // DDoS protection - const maxCrossTxnSize = 4096 - if s := len(node.pendingCXReceipts); s >= maxCrossTxnSize { - utils.Logger().Info(). - Int("pending-cx-receipts-size", s). - Int("pending-cx-receipts-limit", maxCrossTxnSize). - Msg("Current pending cx-receipts reached size limit") - return - } - - if _, ok := node.pendingCXReceipts[key]; ok { - utils.Logger().Info(). - Int("totalPendingReceipts", len(node.pendingCXReceipts)). - Msg("Already Got Same Receipt message") - return - } - node.pendingCXReceipts[key] = receipts - utils.Logger().Info(). - Int("totalPendingReceipts", len(node.pendingCXReceipts)). - Msg("Got ONE more receipt message") + node.Consensus.AddPendingReceipts(receipts) } type withError struct { @@ -1108,11 +1045,10 @@ func New( node.registry.SetTxPool(node.TxPool) node.CxPool = node.registry.GetCxPool() node.Worker = worker.New(blockchain, beaconChain) + node.registry.SetWorker(node.Worker) node.deciderCache, _ = lru.New(16) node.committeeCache, _ = lru.New(16) - - node.pendingCXReceipts = map[string]*types.CXReceiptsProof{} node.Consensus.VerifiedNewBlock = make(chan *types.Block, 1) // the sequence number is the next block number to be added in consensus protocol, which is // always one more than current chain header block diff --git a/node/node_newblock.go b/node/node_newblock.go index 107c36247d..2b4023a62f 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -1,414 +1 @@ package node - -import ( - "sort" - "strings" - "time" - - "github.com/harmony-one/harmony/consensus" - "github.com/harmony-one/harmony/core" - "github.com/harmony-one/harmony/crypto/bls" - "github.com/pkg/errors" - - staking "github.com/harmony-one/harmony/staking/types" - - "github.com/ethereum/go-ethereum/common" - "github.com/harmony-one/harmony/core/rawdb" - "github.com/harmony-one/harmony/core/types" - "github.com/harmony-one/harmony/internal/utils" - "github.com/harmony-one/harmony/shard" -) - -// Constants of proposing a new block -const ( - SleepPeriod = 20 * time.Millisecond - IncomingReceiptsLimit = 6000 // 2000 * (numShards - 1) -) - -// WaitForConsensusReadyV2 listen for the readiness signal from consensus and generate new block for consensus. -// only leader will receive the ready signal -func (node *Node) WaitForConsensusReadyV2(cs *consensus.Consensus, stopChan chan struct{}, stoppedChan chan struct{}) { - go func() { - // Setup stoppedChan - defer close(stoppedChan) - - utils.Logger().Debug(). - Msg("Waiting for Consensus ready") - select { - case <-time.After(30 * time.Second): - case <-stopChan: - return - } - - for { - // keep waiting for Consensus ready - select { - case <-stopChan: - utils.Logger().Warn(). - Msg("Consensus new block proposal: STOPPED!") - return - case proposal := <-cs.GetReadySignal(): - for retryCount := 0; retryCount < 3 && cs.IsLeader(); retryCount++ { - time.Sleep(SleepPeriod) - utils.Logger().Info(). - Uint64("blockNum", cs.Blockchain().CurrentBlock().NumberU64()+1). - Bool("asyncProposal", proposal.Type == consensus.AsyncProposal). - Str("called", proposal.Caller). - Msg("PROPOSING NEW BLOCK ------------------------------------------------") - - // Prepare last commit signatures - newCommitSigsChan := make(chan []byte) - - go func() { - waitTime := 0 * time.Second - if proposal.Type == consensus.AsyncProposal { - waitTime = consensus.CommitSigReceiverTimeout - } - select { - case <-time.After(waitTime): - if waitTime == 0 { - utils.Logger().Info().Msg("[ProposeNewBlock] Sync block proposal, reading commit sigs directly from DB") - } else { - utils.Logger().Info().Msg("[ProposeNewBlock] Timeout waiting for commit sigs, reading directly from DB") - } - sigs, err := cs.BlockCommitSigs(cs.Blockchain().CurrentBlock().NumberU64()) - - if err != nil { - utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Cannot get commit signatures from last block") - } else { - newCommitSigsChan <- sigs - } - case commitSigs := <-cs.GetCommitSigChannel(): - utils.Logger().Info().Msg("[ProposeNewBlock] received commit sigs asynchronously") - if len(commitSigs) > bls.BLSSignatureSizeInBytes { - newCommitSigsChan <- commitSigs - } - } - }() - newBlock, err := node.ProposeNewBlock(newCommitSigsChan) - if err == nil { - utils.Logger().Info(). - Uint64("blockNum", newBlock.NumberU64()). - Uint64("epoch", newBlock.Epoch().Uint64()). - Uint64("viewID", newBlock.Header().ViewID().Uint64()). - Int("numTxs", newBlock.Transactions().Len()). - Int("numStakingTxs", newBlock.StakingTransactions().Len()). - Int("crossShardReceipts", newBlock.IncomingReceipts().Len()). - Msgf("=========Successfully Proposed New Block, shard: %d epoch: %d number: %d ==========", newBlock.ShardID(), newBlock.Epoch().Uint64(), newBlock.NumberU64()) - - // Send the new block to Consensus so it can be confirmed. - cs.BlockChannel(newBlock) - break - } else { - utils.Logger().Err(err).Int("retryCount", retryCount). - Msg("!!!!!!!!!Failed Proposing New Block!!!!!!!!!") - continue - } - } - } - } - }() -} - -// ProposeNewBlock proposes a new block... -func (node *Node) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error) { - currentHeader := node.Blockchain().CurrentHeader() - nowEpoch, blockNow := currentHeader.Epoch(), currentHeader.Number() - utils.AnalysisStart("ProposeNewBlock", nowEpoch, blockNow) - defer utils.AnalysisEnd("ProposeNewBlock", nowEpoch, blockNow) - - // Update worker's current header and - // state data in preparation to propose/process new transactions - env, err := node.Worker.UpdateCurrent() - 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 ( - leaderKey = node.Consensus.GetLeaderPubKey() - coinbase = node.registry.GetAddressToBLSKey().GetAddressForBLSKey(node.Consensus.GetPublicKeys(), shardState, leaderKey.Object, header.Epoch()) - beneficiary = coinbase - ) - - // After staking, all coinbase will be the address of bls pub key - if node.Blockchain().Config().IsStaking(header.Epoch()) { - blsPubKeyBytes := leaderKey.Object.GetAddress() - coinbase.SetBytes(blsPubKeyBytes[:]) - } - - if coinbase == (common.Address{}) { - return nil, errors.New("[ProposeNewBlock] Failed setting coinbase") - } - - // Must set coinbase here because the operations below depend on it - header.SetCoinbase(coinbase) - - // Get beneficiary based on coinbase - // Before staking, coinbase itself is the beneficial - // After staking, beneficial is the corresponding ECDSA address of the bls key - beneficiary, err = node.Blockchain().GetECDSAFromCoinbase(header) - if err != nil { - return nil, err - } - - // Add VRF - if node.Blockchain().Config().IsVRF(header.Epoch()) { - //generate a new VRF for the current block - if err := node.Consensus.GenerateVrfAndProof(header); err != nil { - return nil, err - } - } - - // Execute all the time except for last block of epoch for shard 0 - if !shard.Schedule.IsLastBlock(header.Number().Uint64()) || node.Consensus.ShardID != 0 { - // Prepare normal and staking transactions retrieved from transaction pool - utils.AnalysisStart("proposeNewBlockChooseFromTxnPool") - - pendingPoolTxs, err := node.TxPool.Pending() - if err != nil { - utils.Logger().Err(err).Msg("Failed to fetch pending transactions") - return nil, err - } - pendingPlainTxs := map[common.Address]types.Transactions{} - pendingStakingTxs := staking.StakingTransactions{} - for addr, poolTxs := range pendingPoolTxs { - plainTxsPerAcc := types.Transactions{} - for _, tx := range poolTxs { - if plainTx, ok := tx.(*types.Transaction); ok { - plainTxsPerAcc = append(plainTxsPerAcc, plainTx) - } else if stakingTx, ok := tx.(*staking.StakingTransaction); ok { - // Only process staking transactions after pre-staking epoch happened. - if node.Blockchain().Config().IsPreStaking(node.Worker.GetCurrentHeader().Epoch()) { - pendingStakingTxs = append(pendingStakingTxs, stakingTx) - } - } else { - utils.Logger().Err(types.ErrUnknownPoolTxType). - Msg("Failed to parse pending transactions") - return nil, types.ErrUnknownPoolTxType - } - } - if plainTxsPerAcc.Len() > 0 { - pendingPlainTxs[addr] = plainTxsPerAcc - } - } - - // Try commit normal and staking transactions based on the current state - // The successfully committed transactions will be put in the proposed block - if err := node.Worker.CommitTransactions( - pendingPlainTxs, pendingStakingTxs, beneficiary, - ); err != nil { - utils.Logger().Error().Err(err).Msg("cannot commit transactions") - return nil, err - } - utils.AnalysisEnd("proposeNewBlockChooseFromTxnPool") - } - - // Prepare incoming cross shard transaction receipts - // These are accepted even during the epoch before hip-30 - // because the destination shard only receives them after - // balance is deducted on source shard. to prevent this from - // being a significant problem, the source shards will stop - // accepting txs destined to the shards which are shutting down - // one epoch prior the shut down - receiptsList := node.proposeReceiptsProof() - if len(receiptsList) != 0 { - if err := node.Worker.CommitReceipts(receiptsList); err != nil { - return nil, err - } - } - - isBeaconchainInCrossLinkEra := node.NodeConfig.ShardID == shard.BeaconChainShardID && - node.Blockchain().Config().IsCrossLink(node.Worker.GetCurrentHeader().Epoch()) - - isBeaconchainInStakingEra := node.NodeConfig.ShardID == shard.BeaconChainShardID && - node.Blockchain().Config().IsStaking(node.Worker.GetCurrentHeader().Epoch()) - - utils.AnalysisStart("proposeNewBlockVerifyCrossLinks") - // Prepare cross links and slashing messages - var crossLinksToPropose types.CrossLinks - if isBeaconchainInCrossLinkEra { - allPending, err := node.Blockchain().ReadPendingCrossLinks() - invalidToDelete := []types.CrossLink{} - if err == nil { - for _, pending := range allPending { - // ReadCrossLink beacon chain usage. - exist, err := node.Blockchain().ReadCrossLink(pending.ShardID(), pending.BlockNum()) - if err == nil || exist != nil { - invalidToDelete = append(invalidToDelete, pending) - utils.Logger().Debug(). - AnErr("[ProposeNewBlock] pending crosslink is already committed onchain", err) - continue - } - last, err := node.Blockchain().ReadShardLastCrossLink(pending.ShardID()) - if err != nil { - utils.Logger().Debug(). - AnErr("[ProposeNewBlock] failed to read last crosslink", err) - // no return - } - // if pending crosslink is older than the last crosslink, delete it and continue - if err == nil && exist == nil && last != nil && last.BlockNum() >= pending.BlockNum() { - invalidToDelete = append(invalidToDelete, pending) - } - - // Crosslink is already verified before it's accepted to pending, - // no need to verify again in proposal. - if !node.Blockchain().Config().IsCrossLink(pending.Epoch()) { - utils.Logger().Debug(). - AnErr("[ProposeNewBlock] pending crosslink that's before crosslink epoch", err) - continue - } - - crossLinksToPropose = append(crossLinksToPropose, pending) - if len(crossLinksToPropose) > 15 { - break - } - } - utils.Logger().Info(). - Msgf("[ProposeNewBlock] Proposed %d crosslinks from %d pending crosslinks", - len(crossLinksToPropose), len(allPending), - ) - } else { - utils.Logger().Warn().Err(err).Msgf( - "[ProposeNewBlock] Unable to Read PendingCrossLinks, number of crosslinks: %d", - len(allPending), - ) - } - if n, err := node.Blockchain().DeleteFromPendingCrossLinks(invalidToDelete); err != nil { - utils.Logger().Error(). - Err(err). - Msg("[ProposeNewBlock] invalid pending cross links failed") - } else if len(invalidToDelete) > 0 { - utils.Logger().Info(). - Int("not-deleted", n). - Int("deleted", len(invalidToDelete)). - Msg("[ProposeNewBlock] deleted invalid pending cross links") - } - } - utils.AnalysisEnd("proposeNewBlockVerifyCrossLinks") - - if isBeaconchainInStakingEra { - // this will set a meaningful w.current.slashes - if err := node.Worker.CollectVerifiedSlashes(); err != nil { - return nil, err - } - } - - node.Worker.ApplyShardReduction() - // Prepare shard state - if shardState, err = node.Blockchain().SuperCommitteeForNextEpoch( - node.Beaconchain(), node.Worker.GetCurrentHeader(), false, - ); err != nil { - return nil, err - } - - viewIDFunc := func() uint64 { - return node.Consensus.GetCurBlockViewID() - } - finalizedBlock, err := node.Worker.FinalizeNewBlock( - commitSigs, viewIDFunc, - coinbase, crossLinksToPropose, shardState, - ) - if err != nil { - utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Failed finalizing the new block") - return nil, err - } - - utils.Logger().Info().Msg("[ProposeNewBlock] verifying the new block header") - // err = node.Blockchain().Validator().ValidateHeader(finalizedBlock, true) - err = core.NewBlockValidator(node.Blockchain()).ValidateHeader(finalizedBlock, true) - - if err != nil { - utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Failed verifying the new block header") - return nil, err - } - - // Save process result in the cache for later use for faster block commitment to db. - result := node.Worker.GetCurrentResult() - node.Blockchain().Processor().CacheProcessorResult(finalizedBlock.Hash(), result) - return finalizedBlock, nil -} - -func (node *Node) proposeReceiptsProof() []*types.CXReceiptsProof { - if !node.Blockchain().Config().HasCrossTxFields(node.Worker.GetCurrentHeader().Epoch()) { - return []*types.CXReceiptsProof{} - } - - numProposed := 0 - validReceiptsList := []*types.CXReceiptsProof{} - pendingReceiptsList := []*types.CXReceiptsProof{} - - node.pendingCXMutex.Lock() - defer node.pendingCXMutex.Unlock() - - // not necessary to sort the list, but we just prefer to process the list ordered by shard and blocknum - pendingCXReceipts := []*types.CXReceiptsProof{} - for _, v := range node.pendingCXReceipts { - pendingCXReceipts = append(pendingCXReceipts, v) - } - - sort.SliceStable(pendingCXReceipts, func(i, j int) bool { - shardCMP := pendingCXReceipts[i].MerkleProof.ShardID < pendingCXReceipts[j].MerkleProof.ShardID - shardEQ := pendingCXReceipts[i].MerkleProof.ShardID == pendingCXReceipts[j].MerkleProof.ShardID - blockCMP := pendingCXReceipts[i].MerkleProof.BlockNum.Cmp( - pendingCXReceipts[j].MerkleProof.BlockNum, - ) == -1 - return shardCMP || (shardEQ && blockCMP) - }) - - m := map[common.Hash]struct{}{} - -Loop: - for _, cxp := range node.pendingCXReceipts { - if numProposed > IncomingReceiptsLimit { - pendingReceiptsList = append(pendingReceiptsList, cxp) - continue - } - // check double spent - if node.Blockchain().IsSpent(cxp) { - utils.Logger().Debug().Interface("cxp", cxp).Msg("[proposeReceiptsProof] CXReceipt is spent") - continue - } - hash := cxp.MerkleProof.BlockHash - // ignore duplicated receipts - if _, ok := m[hash]; ok { - continue - } else { - m[hash] = struct{}{} - } - - for _, item := range cxp.Receipts { - if item.ToShardID != node.Blockchain().ShardID() { - continue Loop - } - } - - if err := core.NewBlockValidator(node.Blockchain()).ValidateCXReceiptsProof(cxp); err != nil { - if strings.Contains(err.Error(), rawdb.MsgNoShardStateFromDB) { - pendingReceiptsList = append(pendingReceiptsList, cxp) - } else { - utils.Logger().Error().Err(err).Msg("[proposeReceiptsProof] Invalid CXReceiptsProof") - } - continue - } - - utils.Logger().Debug().Interface("cxp", cxp).Msg("[proposeReceiptsProof] CXReceipts Added") - validReceiptsList = append(validReceiptsList, cxp) - numProposed = numProposed + len(cxp.Receipts) - } - - node.pendingCXReceipts = make(map[string]*types.CXReceiptsProof) - for _, v := range pendingReceiptsList { - blockNum := v.Header.Number().Uint64() - shardID := v.Header.ShardID() - key := utils.GetPendingCXKey(shardID, blockNum) - node.pendingCXReceipts[key] = v - } - - utils.Logger().Debug().Msgf("[proposeReceiptsProof] number of validReceipts %d", len(validReceiptsList)) - return validReceiptsList -} diff --git a/node/service_setup.go b/node/service_setup.go index 94a34d4f1c..223e7341dd 100644 --- a/node/service_setup.go +++ b/node/service_setup.go @@ -19,7 +19,7 @@ func (node *Node) RegisterValidatorServices() { // Register new block service. node.serviceManager.Register( service.BlockProposal, - blockproposal.New(node.Consensus, node.WaitForConsensusReadyV2), + blockproposal.New(node.Consensus), ) } diff --git a/node/worker/types.go b/node/worker/types.go index 87b7195dd3..f18e5fd4dd 100644 --- a/node/worker/types.go +++ b/node/worker/types.go @@ -1,6 +1,14 @@ package worker -import "github.com/harmony-one/harmony/block" +import ( + "time" + + "github.com/harmony-one/harmony/block" +) + +// CommitSigReceiverTimeout is the timeout for the receiving side of the commit sig +// if timeout, the receiver should instead ready directly from db for the commit sig +const CommitSigReceiverTimeout = 8 * time.Second type Environment interface { CurrentHeader() *block.Header diff --git a/node/worker/worker.go b/node/worker/worker.go index db5d855b0e..d4f504126a 100644 --- a/node/worker/worker.go +++ b/node/worker/worker.go @@ -7,20 +7,17 @@ import ( "sort" "time" - "github.com/harmony-one/harmony/consensus" - "github.com/harmony-one/harmony/consensus/reward" - "github.com/harmony-one/harmony/crypto/bls" - - "github.com/harmony-one/harmony/crypto/hash" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" "github.com/harmony-one/harmony/block" blockfactory "github.com/harmony-one/harmony/block/factory" + "github.com/harmony-one/harmony/consensus/reward" "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" + "github.com/harmony-one/harmony/crypto/bls" + "github.com/harmony-one/harmony/crypto/hash" common2 "github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/utils" @@ -609,7 +606,7 @@ func (w *Worker) FinalizeNewBlock( copyHeader.SetLastCommitBitmap(signers) } sigsReady <- true - case <-time.After(consensus.CommitSigReceiverTimeout): + case <-time.After(CommitSigReceiverTimeout): // Exit goroutine utils.Logger().Warn().Msg("Timeout waiting for commit sigs") } From 878e75bcb0ada6aa909b8d6ed19688943a7f84a0 Mon Sep 17 00:00:00 2001 From: Uladzislau Muraveika Date: Fri, 28 Jun 2024 02:19:03 +0300 Subject: [PATCH 32/66] Fix: travis CI changed the way how we install docker - travis updated (#4703) their basic image and add Docker via docker.list, so I've checked how addon instruction is working under the hood - this is just a tee to sources.list, so I've changed docker.list to have the latest stable Docker --- .travis.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 27e9a96cac..7d28d68d61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,12 +14,10 @@ env: - TEST="bash ./scripts/travis_rosetta_checker.sh" # upgrade docker to latest stable version -addons: - apt: - sources: - - sourceline: deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable - packages: - - docker.io +before_install: + - echo "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list >/dev/null + - sudo apt-get update + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce install: # default working directory with source code is automatically set to From be65e8c60360aed5f315ca2e43a66646b6c1098d Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Wed, 3 Jul 2024 21:30:34 +0330 Subject: [PATCH 33/66] enables p2p transport security by default (#4705) --- cmd/bootnode/main.go | 2 +- internal/configs/node/network.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index dfd503b3d1..6a5e3716d9 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -108,7 +108,7 @@ func main() { logConn := flag.Bool("log_conn", false, "log incoming/outgoing connections") maxConnPerIP := flag.Int("max_conn_per_ip", 10, "max connections number for same ip") forceReachabilityPublic := flag.Bool("force_public", false, "forcing the local node to believe it is reachable externally") - noTransportSecurity := flag.Bool("no_transport_security", true, "disable TLS encrypted transport") + noTransportSecurity := flag.Bool("no_transport_security", false, "disable TLS encrypted transport") muxer := flag.String("muxer", "mplex, yamux", "protocol muxer to mux per-protocol streams (mplex, yamux)") userAgent := flag.String("user_agent", defUserAgent, "explicitly set the user-agent, so we can differentiate from other Go libp2p users") noRelay := flag.Bool("no_relay", true, "no relay services, direct connections between peers only") diff --git a/internal/configs/node/network.go b/internal/configs/node/network.go index b43257ead3..bc70b050df 100644 --- a/internal/configs/node/network.go +++ b/internal/configs/node/network.go @@ -80,7 +80,7 @@ const ( // DefaultWaitForEachPeerToConnect sets the sync configs to connect to neighbor peers one by one and waits for each peer to connect. DefaultWaitForEachPeerToConnect = false // DefaultNoTransportSecurity - DefaultNoTransportSecurity = true + DefaultNoTransportSecurity = false // DefaultNAT enables NAT manager for P2P DefaultNAT = true // DefaultUserAgent set the user agent to differentiate between libp2p users From 74f7b5c0599d129aabdd42dd6dd0a8dea9ff6217 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:01:15 -0400 Subject: [PATCH 34/66] Removed unused parameter disableViewChange. (#4699) --- consensus/consensus.go | 2 -- consensus/view_change.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index d9f96b94fa..a281a8ae7c 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -120,8 +120,6 @@ type Consensus struct { host p2p.Host // MessageSender takes are of sending consensus message and the corresponding retry logic. msgSender *MessageSender - // If true, this consensus will not propose view change. - disableViewChange bool // Have a dedicated reader thread pull from this chan, like in node SlashChan chan slash.Record // How long in second the leader needs to wait to propose a new block. diff --git a/consensus/view_change.go b/consensus/view_change.go index 5525e12266..a0ac6c0f79 100644 --- a/consensus/view_change.go +++ b/consensus/view_change.go @@ -231,7 +231,7 @@ func createTimeout() map[TimeoutType]*utils.Timeout { // startViewChange start the view change process func (consensus *Consensus) startViewChange() { - if consensus.disableViewChange || consensus.isBackup { + if consensus.isBackup { return } From d81611eaaff7cf297d7aca91baab13583c7f946b Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:01:32 -0400 Subject: [PATCH 35/66] Fixed condition which is always true. (#4695) --- core/evm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/evm.go b/core/evm.go index e11726a569..f0cfe16b5d 100644 --- a/core/evm.go +++ b/core/evm.go @@ -171,7 +171,7 @@ func DelegateFn(ref *block.Header, chain ChainContext) vm.DelegateFunc { db.SubBalance(delegate.DelegatorAddress, balanceToBeDeducted) - if rosettaTracer != nil && balanceToBeDeducted != big.NewInt(0) { + if rosettaTracer != nil && balanceToBeDeducted.Sign() != 0 { //add rosetta log rosettaTracer.AddRosettaLog( vm.CALL, From 1bafc6c106175e826d792bb0d32f8d9494951271 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:19:03 -0400 Subject: [PATCH 36/66] Genesis block hash log. (#4712) --- node/node.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/node/node.go b/node/node.go index 80a18e554a..846eaecebb 100644 --- a/node/node.go +++ b/node/node.go @@ -1055,9 +1055,10 @@ func New( node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1) } + h := node.Blockchain().GetHeaderByNumber(0) utils.Logger().Info(). - Interface("genesis block header", node.Blockchain().GetHeaderByNumber(0)). - Msg("Genesis block hash") + Interface("genesis block header", h). + Msgf("Genesis block hash %s", h.Hash()) // Setup initial state of syncing. node.peerRegistrationRecord = map[string]*syncConfig{} // Broadcast double-signers reported by consensus From 6e772e2cd5746a5cf6a24d71c8848e33f1841fe4 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Mon, 15 Jul 2024 20:50:21 +0330 Subject: [PATCH 37/66] small fixes on legacy sync (#4713) --- api/service/legacysync/helpers.go | 11 +++++++---- api/service/legacysync/syncing.go | 2 +- hmy/downloader/shortrange.go | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/api/service/legacysync/helpers.go b/api/service/legacysync/helpers.go index 14dac994d9..57f022787d 100644 --- a/api/service/legacysync/helpers.go +++ b/api/service/legacysync/helpers.go @@ -33,18 +33,21 @@ func getMaxPeerHeight(syncConfig *SyncConfig) (uint64, error) { syncConfig.RemovePeer(peerConfig, fmt.Sprintf("failed getMaxPeerHeight for shard %d with message: %s", syncConfig.ShardID(), err.Error())) return } - utils.Logger().Info().Str("peerIP", peerConfig.peer.IP).Uint64("blockHeight", response.BlockHeight). - Msg("[SYNC] getMaxPeerHeight") - lock.Lock() if response != nil { + lock.Lock() + utils.Logger().Info(). + Str("peerIP", peerConfig.peer.IP). + Uint64("blockHeight", response.BlockHeight). + Msg("[SYNC] getMaxPeerHeight") if response.BlockHeight < math.MaxUint32 { // That's enough for decades. if maxHeight == uint64(math.MaxUint64) || maxHeight < response.BlockHeight { maxHeight = response.BlockHeight } } + lock.Unlock() } - lock.Unlock() + }() return }) diff --git a/api/service/legacysync/syncing.go b/api/service/legacysync/syncing.go index e65ef48742..8746139607 100644 --- a/api/service/legacysync/syncing.go +++ b/api/service/legacysync/syncing.go @@ -883,7 +883,7 @@ func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc core.BlockChain if err := bc.Engine().VerifyHeaderSignature(bc, block.Header(), sig, bitmap); err != nil { return errors.Wrapf(err, "verify header signature %v", block.Hash().String()) } - utils.Logger().Debug().Int64("elapsed time", time.Now().Sub(startTime).Milliseconds()).Msg("[Sync] VerifyHeaderSignature") + utils.Logger().Debug().Int64("elapsed time", time.Since(startTime).Milliseconds()).Msg("[Sync] VerifyHeaderSignature") } err := bc.Engine().VerifyHeader(bc, block.Header(), verifySeal) if err == engine.ErrUnknownAncestor { diff --git a/hmy/downloader/shortrange.go b/hmy/downloader/shortrange.go index 8276911d4f..7aef85c2af 100644 --- a/hmy/downloader/shortrange.go +++ b/hmy/downloader/shortrange.go @@ -312,7 +312,7 @@ func (sh *srHelper) doGetBlocksByNumbersRequest(bns []uint64) ([]*types.Block, s } func (sh *srHelper) doGetBlocksByHashesRequest(ctx context.Context, hashes []common.Hash, wl []sttypes.StreamID) ([]*types.Block, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(sh.ctx, 10*time.Second) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() blocks, stid, err := sh.syncProtocol.GetBlocksByHashes(ctx, hashes, From 350397222ea22d29821622be24ff6a73bde70c2d Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:49:25 -0400 Subject: [PATCH 38/66] 100% coverage for UpdateMaxCommissionFee. (#4708) --- go.sum | 1 - internal/chain/engine.go | 6 +-- staking/availability/measure.go | 29 ++++++------- staking/availability/measure_test.go | 61 +++++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 20 deletions(-) diff --git a/go.sum b/go.sum index 7cff65a977..1e40900e17 100644 --- a/go.sum +++ b/go.sum @@ -1431,7 +1431,6 @@ github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= -github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= diff --git a/internal/chain/engine.go b/internal/chain/engine.go index 5bf8dc629d..d5866e3887 100644 --- a/internal/chain/engine.go +++ b/internal/chain/engine.go @@ -458,7 +458,7 @@ func setElectionEpochAndMinFee(chain engine.ChainReader, header *block.Header, s if config.IsMaxRate(newShardState.Epoch) { for _, addr := range chain.ValidatorCandidates() { - if _, err := availability.UpdateMaxCommissionFee(newShardState.Epoch, config, state, addr, minRate); err != nil { + if err := availability.UpdateMaxCommissionFee(config.IsTopMaxRate(newShardState.Epoch), state, addr, minRate); err != nil { return err } } @@ -486,10 +486,10 @@ func setElectionEpochAndMinFee(chain engine.ChainReader, header *block.Header, s // for all validators which have MaxRate < minRate + maxChangeRate // set their MaxRate equal to the minRate + MaxChangeRate // this will allow the wrapper.SanityCheck to pass if Rate is set to a value - // higher than the the MaxRate by UpdateMinimumCommissionFee above + // higher than the MaxRate by UpdateMinimumCommissionFee above if config.IsMaxRate(newShardState.Epoch) && minRateNotZero { for _, addr := range chain.ValidatorCandidates() { - if _, err := availability.UpdateMaxCommissionFee(newShardState.Epoch, config, state, addr, minRate); err != nil { + if err := availability.UpdateMaxCommissionFee(config.IsTopMaxRate(newShardState.Epoch), state, addr, minRate); err != nil { return err } } diff --git a/staking/availability/measure.go b/staking/availability/measure.go index faa105f261..a1c48845dd 100644 --- a/staking/availability/measure.go +++ b/staking/availability/measure.go @@ -3,11 +3,9 @@ package availability import ( "math/big" - "github.com/harmony-one/harmony/core/state" - "github.com/ethereum/go-ethereum/common" + "github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/crypto/bls" - "github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/shard" @@ -267,33 +265,36 @@ func UpdateMinimumCommissionFee( return false, nil } +type stateValidatorWrapper interface { + ValidatorWrapper(addr common.Address, sendOriginal bool, copyDelegations bool) (*staking.ValidatorWrapper, error) +} + // UpdateMaxCommissionFee makes sure the max-rate is at least higher than the rate + max-rate-change. -func UpdateMaxCommissionFee(epoch *big.Int, config *params.ChainConfig, state *state.DB, addr common.Address, minRate numeric.Dec) (bool, error) { +func UpdateMaxCommissionFee(IsTopMaxRate bool, state stateValidatorWrapper, addr common.Address, curRate numeric.Dec) error { utils.Logger().Info().Msg("begin update max commission fee") wrapper, err := state.ValidatorWrapper(addr, true, false) if err != nil { - return false, err + return err } - minMaxRate := minRate.Add(wrapper.MaxChangeRate) + newRate := curRate.Add(wrapper.MaxChangeRate) - if config.IsTopMaxRate(epoch) { + if IsTopMaxRate { hundredPercent := numeric.NewDec(1) - if minMaxRate.GT(hundredPercent) { - minMaxRate = hundredPercent + if newRate.GT(hundredPercent) { + newRate = hundredPercent } } - if wrapper.MaxRate.LT(minMaxRate) { + if wrapper.MaxRate.LT(newRate) { utils.Logger().Info(). Str("addr", addr.Hex()). Str("old max-rate", wrapper.MaxRate.String()). - Str("new max-rate", minMaxRate.String()). + Str("new max-rate", newRate.String()). Msg("updating max commission rate") - wrapper.MaxRate.SetBytes(minMaxRate.Bytes()) - return true, nil + wrapper.MaxRate.SetBytes(newRate.Bytes()) } - return false, nil + return nil } diff --git a/staking/availability/measure_test.go b/staking/availability/measure_test.go index 393d19bb4f..b3a26d8172 100644 --- a/staking/availability/measure_test.go +++ b/staking/availability/measure_test.go @@ -7,14 +7,14 @@ import ( "reflect" "testing" - "github.com/harmony-one/harmony/crypto/bls" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" + "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/staking/effective" staking "github.com/harmony-one/harmony/staking/types" + "github.com/stretchr/testify/require" ) func TestBlockSigners(t *testing.T) { @@ -731,3 +731,60 @@ func makeTestWrapper(addr common.Address, numSigned, numToSign int64) staking.Va val.Counters.NumBlocksSigned = new(big.Int).SetInt64(numSigned) return val } + +type stateValidatorWrapperImpl struct { + v *staking.ValidatorWrapper + err error +} + +func (a stateValidatorWrapperImpl) ValidatorWrapper(addr common.Address, sendOriginal bool, copyDelegations bool) (*staking.ValidatorWrapper, error) { + return a.v, a.err +} + +func TestUpdateMaxCommissionFee(t *testing.T) { + t.Run("0.6 + 0.6 = 1 (100%)", func(t *testing.T) { + v1 := stateValidatorWrapperImpl{ + v: &staking.ValidatorWrapper{ + Validator: staking.Validator{ + Commission: staking.Commission{ + CommissionRates: staking.CommissionRates{ + MaxChangeRate: numeric.MustNewDecFromStr("0.6"), + MaxRate: numeric.MustNewDecFromStr("0.95"), + }, + }, + }, + }, + } + + err := UpdateMaxCommissionFee(true, v1, common.Address{}, numeric.MustNewDecFromStr("0.6")) + require.NoError(t, err) + require.Equal(t, "1.000000000000000000", v1.v.Commission.CommissionRates.MaxRate.String()) + }) + + t.Run("0.07 + 0.5 = 0.57", func(t *testing.T) { + v2 := stateValidatorWrapperImpl{ + v: &staking.ValidatorWrapper{ + Validator: staking.Validator{ + Commission: staking.Commission{ + CommissionRates: staking.CommissionRates{ + MaxChangeRate: numeric.MustNewDecFromStr("0.5"), + MaxRate: numeric.MustNewDecFromStr("0"), + }, + }, + }, + }, + } + err := UpdateMaxCommissionFee(true, v2, common.Address{}, numeric.MustNewDecFromStr("0.07")) + require.NoError(t, err) + require.Equal(t, "0.570000000000000000", v2.v.Commission.CommissionRates.MaxRate.String()) + }) + + t.Run("error", func(t *testing.T) { + s := stateValidatorWrapperImpl{ + v: &staking.ValidatorWrapper{}, + err: errors.New("error"), + } + err := UpdateMaxCommissionFee(true, s, common.Address{}, numeric.MustNewDecFromStr("0.07")) + require.Error(t, err) + }) +} From 8306c60cf2f146e96e942ac959bba3f527cf8c78 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:55:20 -0400 Subject: [PATCH 39/66] Fixed PeerStore usage. (#4706) --- node/node_handler.go | 7 ++++--- p2p/host.go | 19 ++++++++----------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/node/node_handler.go b/node/node_handler.go index 011d5d0771..7aa87100bb 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -421,16 +421,17 @@ func (node *Node) BootstrapConsensus() error { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() min := node.Consensus.MinPeers - enoughMinPeers := make(chan struct{}) + enoughMinPeers := make(chan struct{}, 1) const checkEvery = 3 * time.Second go func() { for { <-time.After(checkEvery) numPeersNow := node.host.GetPeerCount() - if numPeersNow >= min { + connectedPeers := len(node.host.Network().Peers()) + if connectedPeers >= min { utils.Logger().Info().Msg("[bootstrap] StartConsensus") enoughMinPeers <- struct{}{} - fmt.Println("Bootstrap consensus done.", numPeersNow, " peers are connected") + fmt.Printf("Bootstrap consensus done. Connected %d, known %d, shard: %d\n", connectedPeers, numPeersNow, node.Consensus.ShardID) return } utils.Logger().Info(). diff --git a/p2p/host.go b/p2p/host.go index 258942d6c7..df2276ab7c 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -57,6 +57,7 @@ type Host interface { GetID() libp2p_peer.ID GetP2PHost() libp2p_host.Host GetDiscovery() discovery.Discovery + Network() libp2p_network.Network GetPeerCount() int ConnectHostPeer(Peer) error // AddStreamProtocol add the given protocol @@ -443,17 +444,9 @@ func (host *HostV2) Close() error { // PeerConnectivity returns total number of known, connected and not connected peers. func (host *HostV2) PeerConnectivity() (int, int, int) { - connected, not := 0, 0 - peers := host.h.Peerstore().Peers() - for _, peer := range peers { - result := host.h.Network().Connectedness(peer) - if result == libp2p_network.Connected { - connected++ - } else if result == libp2p_network.NotConnected { - not++ - } - } - return len(peers), connected, not + known := len(host.h.Peerstore().Peers()) + connected := len(host.h.Network().Peers()) + return known, connected, known - connected } // AddStreamProtocol adds the stream protocols to the host to be started and closed @@ -589,6 +582,10 @@ func (host *HostV2) GetPeerCount() int { return host.h.Peerstore().Peers().Len() } +func (host *HostV2) Network() libp2p_network.Network { + return host.h.Network() +} + // ConnectHostPeer connects to peer host func (host *HostV2) ConnectHostPeer(peer Peer) error { ctx := context.Background() From a65cf7175dc708144aacdecaaa6bb725a9f4f3f9 Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Fri, 19 Jul 2024 00:01:55 -0400 Subject: [PATCH 40/66] Fixed data race. (#4686) --- core/blockchain_impl.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/blockchain_impl.go b/core/blockchain_impl.go index d71371986e..a065ecfd6d 100644 --- a/core/blockchain_impl.go +++ b/core/blockchain_impl.go @@ -490,6 +490,9 @@ func (bc *BlockChainImpl) ValidateNewBlock(block *types.Block, beaconChain Block if block.NumberU64() <= bc.CurrentBlock().NumberU64() { return errors.Errorf("block with the same block number is already committed: %d", block.NumberU64()) } + + bc.chainmu.Lock() + defer bc.chainmu.Unlock() if err := bc.validator.ValidateHeader(block, true); err != nil { utils.Logger().Error(). Str("blockHash", block.Hash().Hex()). From 16fe018c8471460538d50c892e1f1cdf3f8966d4 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Fri, 19 Jul 2024 10:31:01 +0330 Subject: [PATCH 41/66] fix lock release issue in stream sync (#4714) --- api/service/stagedstreamsync/staged_stream_sync.go | 3 +++ api/service/stagedstreamsync/state_sync_full.go | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/api/service/stagedstreamsync/staged_stream_sync.go b/api/service/stagedstreamsync/staged_stream_sync.go index 1782068b29..7aef457ef8 100644 --- a/api/service/stagedstreamsync/staged_stream_sync.go +++ b/api/service/stagedstreamsync/staged_stream_sync.go @@ -248,6 +248,9 @@ func (s *StagedStreamSync) cleanUp(ctx context.Context, fromStage int, db kv.RwD continue } if err := s.pruneStage(ctx, firstCycle, s.pruningOrder[i], db, tx); err != nil { + utils.Logger().Error().Err(err). + Interface("stage id", s.pruningOrder[i].ID). + Msgf(WrapStagedSyncMsg("stage cleanup failed")) panic(err) } } diff --git a/api/service/stagedstreamsync/state_sync_full.go b/api/service/stagedstreamsync/state_sync_full.go index 14cdb1f594..cb7d40d945 100644 --- a/api/service/stagedstreamsync/state_sync_full.go +++ b/api/service/stagedstreamsync/state_sync_full.go @@ -789,7 +789,7 @@ func (s *FullStateDownloadManager) cleanAccountTasks() { return } // Sync wasn't finished previously, check for any task that can be finalized - for taskID, _ := range s.tasks.accountTasks { + for taskID := range s.tasks.accountTasks { if s.tasks.accountTasks[taskID].done { s.tasks.deleteAccountTask(taskID) } @@ -2333,7 +2333,7 @@ func (s *FullStateDownloadManager) onHealByteCodes(task *healTask, Msg("Delivering set of healing bytecodes") s.lock.Lock() - s.lock.Unlock() + defer s.lock.Unlock() // Response is valid, but check if peer is signalling that it does not have // the requested data. For bytecode range queries that means the peer is not From 73df9c534d97481794e946a1d93f3cd8b14deb54 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Fri, 19 Jul 2024 11:07:32 +0330 Subject: [PATCH 42/66] update a few of deprecated dependencies (#4715) --- core/tx_journal.go | 2 +- go.mod | 2 +- go.sum | 3 +++ internal/blsgen/console.go | 2 +- internal/configs/harmony/harmony.go | 5 ++++- internal/utils/passphrase.go | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/tx_journal.go b/core/tx_journal.go index e6a305b33c..4b541ebb7c 100644 --- a/core/tx_journal.go +++ b/core/tx_journal.go @@ -116,7 +116,7 @@ func (journal *txJournal) load(add func(types.PoolTransactions) []error) error { for { // Parse the next transaction and terminate on errors var tx types.PoolTransaction - switch txType, err := stream.Uint(); txType { + switch txType, err := stream.Uint64(); txType { case plainTxID: tx = new(types.Transaction) case stakingTxID: diff --git a/go.mod b/go.mod index 2a808e818e..7f17e5b912 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( golang.org/x/time v0.3.0 golang.org/x/tools v0.14.0 // indirect google.golang.org/grpc v1.55.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.34.2 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 diff --git a/go.sum b/go.sum index 1e40900e17..fe61a05100 100644 --- a/go.sum +++ b/go.sum @@ -1431,6 +1431,7 @@ github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= +github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= @@ -2110,6 +2111,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/blsgen/console.go b/internal/blsgen/console.go index 1320f5f4de..d6079d9cf8 100644 --- a/internal/blsgen/console.go +++ b/internal/blsgen/console.go @@ -7,7 +7,7 @@ import ( "strings" "syscall" - "golang.org/x/crypto/ssh/terminal" + terminal "golang.org/x/term" ) var console consoleItf = &stdConsole{} diff --git a/internal/configs/harmony/harmony.go b/internal/configs/harmony/harmony.go index 4fa58acdd8..beb2809c02 100644 --- a/internal/configs/harmony/harmony.go +++ b/internal/configs/harmony/harmony.go @@ -8,6 +8,8 @@ import ( nodeconfig "github.com/harmony-one/harmony/internal/configs/node" "github.com/harmony-one/harmony/internal/utils" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) // HarmonyConfig contains all the configs user can set for running harmony binary. Served as the bridge @@ -253,8 +255,9 @@ type LogVerbosePrints struct { func FlagSliceToLogVerbosePrints(verbosePrintsFlagSlice []string) LogVerbosePrints { verbosePrints := LogVerbosePrints{} verbosePrintsReflect := reflect.Indirect(reflect.ValueOf(&verbosePrints)) + caser := cases.Title(language.English) for _, verbosePrint := range verbosePrintsFlagSlice { - verbosePrint = strings.Title(verbosePrint) + verbosePrint = caser.String(strings.ToLower(verbosePrint)) field := verbosePrintsReflect.FieldByName(verbosePrint) if field.IsValid() && field.CanSet() { field.SetBool(true) diff --git a/internal/utils/passphrase.go b/internal/utils/passphrase.go index 35b7606a7c..b57d20fe4d 100644 --- a/internal/utils/passphrase.go +++ b/internal/utils/passphrase.go @@ -9,7 +9,7 @@ import ( "syscall" "github.com/pkg/errors" - "golang.org/x/crypto/ssh/terminal" + terminal "golang.org/x/term" ) // AskForPassphrase return passphrase using password input From 252bda95851cbd9a2660d9f0b55bfe511389d58c Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Fri, 19 Jul 2024 03:39:37 -0400 Subject: [PATCH 43/66] Removed trailing zeros. (#4709) --- numeric/decimal.go | 55 +++++++++++++++++++++++++++------------ numeric/decimal_test.go | 54 ++++++++++++++++++++++++++------------ shard/shard_state_test.go | 2 +- 3 files changed, 78 insertions(+), 33 deletions(-) diff --git a/numeric/decimal.go b/numeric/decimal.go index f80c9eca14..b29ca64d48 100644 --- a/numeric/decimal.go +++ b/numeric/decimal.go @@ -383,32 +383,45 @@ func (d Dec) String() string { var bzStr []byte - // TODO: Remove trailing zeros // case 1, purely decimal if inputSize <= Precision { - bzStr = make([]byte, Precision+2) + bzStr = make([]byte, 0, Precision+2) // 0. prefix - bzStr[0] = byte('0') - bzStr[1] = byte('.') - - // set relevant digits to 0 - for i := 0; i < Precision-inputSize; i++ { - bzStr[i+2] = byte('0') + bzStr = append(bzStr, byte('0')) + if !IsZeroes(bzInt) { + bzStr = append(bzStr, '.') + + // set relevant digits to 0 + for i := 0; i < Precision-inputSize; i++ { + bzStr = append(bzStr, byte('0')) + } + + // set final digits + for len(bzInt) > 0 { + if !IsZeroes(bzInt) { + bzStr = append(bzStr, bzInt[0]) + } + bzInt = bzInt[1:] + } } - // set final digits - copy(bzStr[2+(Precision-inputSize):], bzInt) - } else { - // inputSize + 1 to account for the decimal point that is being added - bzStr = make([]byte, inputSize+1) + bzStr = make([]byte, 0, inputSize+1) decPointPlace := inputSize - Precision - copy(bzStr, bzInt[:decPointPlace]) // pre-decimal digits - bzStr[decPointPlace] = byte('.') // decimal point - copy(bzStr[decPointPlace+1:], bzInt[decPointPlace:]) // post-decimal digits + bzStr = append(bzStr, bzInt[:decPointPlace]...) // pre-decimal digits + if !IsZeroes(bzInt[decPointPlace:]) { + bzStr = append(bzStr, byte('.')) // decimal point + } + bzInt = bzInt[decPointPlace:] // post-decimal digits + for len(bzInt) > 0 { + if !IsZeroes(bzInt) { + bzStr = append(bzStr, bzInt[0]) + } + bzInt = bzInt[1:] + } } if isNeg { @@ -418,6 +431,16 @@ func (d Dec) String() string { return string(bzStr) } +// IsZeroes checks if the byte array is all zeroes +func IsZeroes(b []byte) bool { + for _, c := range b { + if c != '0' { + return false + } + } + return true +} + // ____ // __| |__ "chop 'em // ` \ round!" diff --git a/numeric/decimal_test.go b/numeric/decimal_test.go index 7b790f20de..40b9e116d0 100644 --- a/numeric/decimal_test.go +++ b/numeric/decimal_test.go @@ -99,14 +99,15 @@ func TestDecString(t *testing.T) { d Dec want string }{ - {NewDec(0), "0.000000000000000000"}, - {NewDec(1), "1.000000000000000000"}, - {NewDec(10), "10.000000000000000000"}, - {NewDec(12340), "12340.000000000000000000"}, - {NewDecWithPrec(12340, 4), "1.234000000000000000"}, - {NewDecWithPrec(12340, 5), "0.123400000000000000"}, - {NewDecWithPrec(12340, 8), "0.000123400000000000"}, - {NewDecWithPrec(1009009009009009009, 17), "10.090090090090090090"}, + {NewDec(0), "0"}, + {NewDec(1), "1"}, + {NewDec(10), "10"}, + {NewDec(12340), "12340"}, + {NewDecWithPrec(12340, 4), "1.234"}, + {NewDecWithPrec(12340, 5), "0.1234"}, + {NewDecWithPrec(12340, 8), "0.0001234"}, + {NewDecWithPrec(1009009009009009009, 17), "10.09009009009009009"}, + {Dec{Int: nil}, ""}, } for tcIndex, tc := range tests { assert.Equal(t, tc.want, tc.d.String(), "bad String(), index: %v", tcIndex) @@ -297,14 +298,14 @@ func TestDecMarshalJSON(t *testing.T) { want string wantErr bool // if wantErr = false, will also attempt unmarshaling }{ - {"zero", decimal(0), "\"0.000000000000000000\"", false}, + {"zero", decimal(0), "\"0\"", false}, {"one", decimal(1), "\"0.000000000000000001\"", false}, - {"ten", decimal(10), "\"0.000000000000000010\"", false}, - {"12340", decimal(12340), "\"0.000000000000012340\"", false}, - {"zeroInt", NewDec(0), "\"0.000000000000000000\"", false}, - {"oneInt", NewDec(1), "\"1.000000000000000000\"", false}, - {"tenInt", NewDec(10), "\"10.000000000000000000\"", false}, - {"12340Int", NewDec(12340), "\"12340.000000000000000000\"", false}, + {"ten", decimal(10), "\"0.00000000000000001\"", false}, + {"12340", decimal(12340), "\"0.00000000000001234\"", false}, + {"zeroInt", NewDec(0), "\"0\"", false}, + {"oneInt", NewDec(1), "\"1\"", false}, + {"tenInt", NewDec(10), "\"10\"", false}, + {"12340Int", NewDec(12340), "\"12340\"", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -343,7 +344,7 @@ func TestStringOverflow(t *testing.T) { require.NoError(t, err) dec3 := dec1.Add(dec2) require.Equal(t, - "19844653375691057515930281852116324640.000000000000000000", + "19844653375691057515930281852116324640", dec3.String(), ) } @@ -390,5 +391,26 @@ func TestDiv(t *testing.T) { res := tc.d1.Quo(tc.d2) require.True(t, res.Equal(tc.exp), "unexpected result for test case %d, input: %s %s %s", i, tc.d1, tc.d2, tc.exp) } +} +func TestIsZeroes(t *testing.T) { + tests := []struct { + d []byte + want bool + }{ + {[]byte{}, true}, + {[]byte{'0'}, true}, + {[]byte{'1'}, false}, + {[]byte{'0', '0'}, true}, + {[]byte{'0', '1'}, false}, + {[]byte{'1', '0'}, false}, + {[]byte{'1', '1'}, false}, + {[]byte{'0', '0', '0'}, true}, + {[]byte{'0', '0', '1'}, false}, + } + + for i, tc := range tests { + res := IsZeroes(tc.d) + require.Equal(t, tc.want, res, "unexpected result for test case index %d, expected %v, value %s", i, tc.want, tc.d) + } } diff --git a/shard/shard_state_test.go b/shard/shard_state_test.go index ab3c162443..54a2d9200f 100644 --- a/shard/shard_state_test.go +++ b/shard/shard_state_test.go @@ -23,7 +23,7 @@ var ( const ( json1 = `[{"shard-id":0,"member-count":4,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792034000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]},{"shard-id":1,"member-count":2,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792036000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]}]` - json2 = `[{"shard-id":0,"member-count":5,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10.000000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]},{"shard-id":1,"member-count":4,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10.000000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792034000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]}]` + json2 = `[{"shard-id":0,"member-count":5,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]},{"shard-id":1,"member-count":4,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792034000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]}]` ) func init() { From 900529d94492b45c50c9ef7e12b57a8c66732016 Mon Sep 17 00:00:00 2001 From: Gheis Mohammadi Date: Fri, 19 Jul 2024 11:10:56 +0330 Subject: [PATCH 44/66] add linux static quick command to make file (#4704) --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 906e8c06a0..f42dd76f87 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,9 @@ linux_static: make -C $(TOP)/bls minimised_static BLS_SWAP_G=1 -j8 bash ./scripts/go_executable_build.sh -s +linux_static_quick: + bash ./scripts/go_executable_build.sh -s + deb_init: rm -rf $(DEBBUILD) mkdir -p $(DEBBUILD)/$(PKGNAME)-$(VERSION)-$(RELEASE)/{etc/systemd/system,usr/sbin,etc/sysctl.d,etc/harmony} From 0e74201334b0d253462c2aaa899116fc4b2a743c Mon Sep 17 00:00:00 2001 From: Konstantin <355847+Frozen@users.noreply.github.com> Date: Mon, 22 Jul 2024 20:57:05 -0400 Subject: [PATCH 45/66] Broadcast sign power (#4683) --- Makefile | 3 + api/proto/message/message.pb.go | 413 +++++++++++++++++++++----------- api/proto/message/message.proto | 10 + consensus/consensus.go | 15 ++ consensus/consensus_service.go | 46 ++++ consensus/consensus_v2.go | 10 + consensus/fbft_log.go | 1 + node/api.go | 26 +- node/node.go | 28 ++- 9 files changed, 378 insertions(+), 174 deletions(-) diff --git a/Makefile b/Makefile index f42dd76f87..f6c39a66f2 100644 --- a/Makefile +++ b/Makefile @@ -183,3 +183,6 @@ debug_external: clean build_localnet_validator: bash test/build-localnet-validator.sh + +generate: + bash ./scripts/gogenerate.sh diff --git a/api/proto/message/message.pb.go b/api/proto/message/message.pb.go index b1367f3d7d..1ba44920ae 100644 --- a/api/proto/message/message.pb.go +++ b/api/proto/message/message.pb.go @@ -94,6 +94,7 @@ const ( MessageType_DRAND_COMMIT MessageType = 11 // Deprecated: Marked as deprecated in message.proto. MessageType_LOTTERY_REQUEST MessageType = 12 // it should be either ENTER or GETPLAYERS but it will be removed later. + MessageType_LAST_SIGN_POWER MessageType = 13 ) // Enum value maps for MessageType. @@ -110,6 +111,7 @@ var ( 10: "DRAND_INIT", 11: "DRAND_COMMIT", 12: "LOTTERY_REQUEST", + 13: "LAST_SIGN_POWER", } MessageType_value = map[string]int32{ "NEWNODE_BEACON_STAKING": 0, @@ -123,6 +125,7 @@ var ( "DRAND_INIT": 10, "DRAND_COMMIT": 11, "LOTTERY_REQUEST": 12, + "LAST_SIGN_POWER": 13, } ) @@ -225,6 +228,7 @@ type Message struct { // *Message_Drand // *Message_Viewchange // *Message_LotteryRequest + // *Message_LastSignPower Request isMessage_Request `protobuf_oneof:"request"` } @@ -326,6 +330,13 @@ func (x *Message) GetLotteryRequest() *LotteryRequest { return nil } +func (x *Message) GetLastSignPower() *LastSignPowerRequest { + if x, ok := x.GetRequest().(*Message_LastSignPower); ok { + return x.LastSignPower + } + return nil +} + type isMessage_Request interface { isMessage_Request() } @@ -355,6 +366,10 @@ type Message_LotteryRequest struct { LotteryRequest *LotteryRequest `protobuf:"bytes,8,opt,name=lottery_request,json=lotteryRequest,proto3,oneof"` } +type Message_LastSignPower struct { + LastSignPower *LastSignPowerRequest `protobuf:"bytes,9,opt,name=last_sign_power,json=lastSignPower,proto3,oneof"` +} + func (*Message_Staking) isMessage_Request() {} func (*Message_Consensus) isMessage_Request() {} @@ -365,6 +380,8 @@ func (*Message_Viewchange) isMessage_Request() {} func (*Message_LotteryRequest) isMessage_Request() {} +func (*Message_LastSignPower) isMessage_Request() {} + type Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -820,6 +837,85 @@ func (x *DrandRequest) GetPayload() []byte { return nil } +type LastSignPowerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prepare int64 `protobuf:"varint,1,opt,name=prepare,proto3" json:"prepare,omitempty"` + Commit int64 `protobuf:"varint,2,opt,name=commit,proto3" json:"commit,omitempty"` + Change int64 `protobuf:"varint,3,opt,name=change,proto3" json:"change,omitempty"` + SenderPubkey []byte `protobuf:"bytes,4,opt,name=sender_pubkey,json=senderPubkey,proto3" json:"sender_pubkey,omitempty"` + ShardId uint32 `protobuf:"varint,5,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` +} + +func (x *LastSignPowerRequest) Reset() { + *x = LastSignPowerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_message_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LastSignPowerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LastSignPowerRequest) ProtoMessage() {} + +func (x *LastSignPowerRequest) ProtoReflect() protoreflect.Message { + mi := &file_message_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LastSignPowerRequest.ProtoReflect.Descriptor instead. +func (*LastSignPowerRequest) Descriptor() ([]byte, []int) { + return file_message_proto_rawDescGZIP(), []int{7} +} + +func (x *LastSignPowerRequest) GetPrepare() int64 { + if x != nil { + return x.Prepare + } + return 0 +} + +func (x *LastSignPowerRequest) GetCommit() int64 { + if x != nil { + return x.Commit + } + return 0 +} + +func (x *LastSignPowerRequest) GetChange() int64 { + if x != nil { + return x.Change + } + return 0 +} + +func (x *LastSignPowerRequest) GetSenderPubkey() []byte { + if x != nil { + return x.SenderPubkey + } + return nil +} + +func (x *LastSignPowerRequest) GetShardId() uint32 { + if x != nil { + return x.ShardId + } + return 0 +} + type ViewChangeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -845,7 +941,7 @@ type ViewChangeRequest struct { func (x *ViewChangeRequest) Reset() { *x = ViewChangeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[7] + mi := &file_message_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -858,7 +954,7 @@ func (x *ViewChangeRequest) String() string { func (*ViewChangeRequest) ProtoMessage() {} func (x *ViewChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[7] + mi := &file_message_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -871,7 +967,7 @@ func (x *ViewChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ViewChangeRequest.ProtoReflect.Descriptor instead. func (*ViewChangeRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{7} + return file_message_proto_rawDescGZIP(), []int{8} } func (x *ViewChangeRequest) GetViewId() uint64 { @@ -969,7 +1065,7 @@ var File_message_proto protoreflect.FileDescriptor var file_message_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc2, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x73, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8b, 0x04, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, @@ -997,120 +1093,136 @@ var file_message_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x0e, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x49, 0x0a, - 0x10, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x0f, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x0f, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x6c, - 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x54, 0x79, 0x70, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, - 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x3a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x05, 0x45, 0x4e, 0x54, 0x45, 0x52, - 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0e, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, - 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x13, 0x0a, 0x0b, 0x50, 0x49, 0x43, 0x4b, 0x5f, 0x57, - 0x49, 0x4e, 0x4e, 0x45, 0x52, 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x22, 0x53, 0x0a, 0x0e, 0x53, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, - 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, - 0x22, 0x89, 0x02, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, - 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x69, 0x74, 0x6d, - 0x61, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x22, 0x97, 0x01, 0x0a, - 0x0c, 0x44, 0x72, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, - 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x42, - 0x02, 0x18, 0x01, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0d, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xad, 0x03, 0x0a, 0x11, 0x56, 0x69, 0x65, 0x77, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, - 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, - 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, - 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, - 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, - 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, - 0x73, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x69, 0x65, 0x77, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x65, 0x77, - 0x69, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x69, - 0x65, 0x77, 0x69, 0x64, 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x32, 0x5f, 0x61, 0x67, - 0x67, 0x73, 0x69, 0x67, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x32, 0x41, - 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x32, 0x5f, 0x62, 0x69, 0x74, - 0x6d, 0x61, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x32, 0x42, 0x69, 0x74, - 0x6d, 0x61, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x33, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, - 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x33, 0x41, 0x67, 0x67, 0x73, 0x69, - 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x33, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x33, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, - 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, - 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2a, 0x50, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, - 0x55, 0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0d, 0x0a, 0x05, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x10, 0x02, - 0x1a, 0x02, 0x08, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x53, - 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x03, 0x2a, 0xd1, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x16, 0x4e, 0x45, 0x57, 0x4e, - 0x4f, 0x44, 0x45, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4b, 0x49, - 0x4e, 0x47, 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x4e, 0x4f, - 0x55, 0x4e, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, - 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x44, 0x10, - 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a, - 0x09, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, - 0x56, 0x49, 0x45, 0x57, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, - 0x4e, 0x45, 0x57, 0x56, 0x49, 0x45, 0x57, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0a, 0x44, 0x52, 0x41, - 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x0a, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x14, 0x0a, - 0x0c, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0b, 0x1a, - 0x02, 0x08, 0x01, 0x12, 0x17, 0x0a, 0x0f, 0x4c, 0x4f, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x52, - 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x0c, 0x1a, 0x02, 0x08, 0x01, 0x32, 0x41, 0x0a, 0x0d, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, - 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x10, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x12, 0x47, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x5f, + 0x70, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, + 0x77, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x6c, 0x61, + 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x49, 0x0a, 0x10, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, + 0x79, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, + 0x52, 0x0f, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, + 0x0f, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x1e, + 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xc3, + 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1c, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x42, 0x02, 0x18, + 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0d, 0x0a, 0x05, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01, 0x12, + 0x0e, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, 0x12, + 0x13, 0x0a, 0x0b, 0x50, 0x49, 0x43, 0x4b, 0x5f, 0x57, 0x49, 0x4e, 0x4e, 0x45, 0x52, 0x10, 0x02, + 0x1a, 0x02, 0x08, 0x01, 0x22, 0x53, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, + 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x07, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, + 0x01, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x89, 0x02, 0x0a, 0x10, 0x43, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, + 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, + 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x12, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x42, + 0x69, 0x74, 0x6d, 0x61, 0x70, 0x22, 0x97, 0x01, 0x0a, 0x0c, 0x44, 0x72, 0x61, 0x6e, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x73, 0x68, + 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x21, + 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, + 0x68, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, + 0xa0, 0x01, 0x0a, 0x14, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, 0x77, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x70, + 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x70, 0x72, 0x65, 0x70, 0x61, + 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, + 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x49, 0x64, 0x22, 0xad, 0x03, 0x0a, 0x11, 0x56, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, + 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, + 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x25, 0x0a, + 0x0e, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, 0x5f, 0x73, + 0x69, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, + 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x32, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, + 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x32, 0x41, 0x67, 0x67, 0x73, 0x69, + 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x32, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x32, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, + 0x1d, 0x0a, 0x0a, 0x6d, 0x33, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x33, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x12, 0x1b, + 0x0a, 0x09, 0x6d, 0x33, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x08, 0x6d, 0x33, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, + 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x2a, 0x50, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x10, 0x00, + 0x12, 0x0f, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, 0x02, 0x08, + 0x01, 0x12, 0x0d, 0x0a, 0x05, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, + 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x55, 0x50, 0x50, 0x4f, + 0x52, 0x54, 0x10, 0x03, 0x2a, 0xe6, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x16, 0x4e, 0x45, 0x57, 0x4e, 0x4f, 0x44, 0x45, 0x5f, + 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x00, + 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x02, 0x12, + 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, + 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, + 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x49, 0x45, 0x57, + 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x45, 0x57, 0x56, + 0x49, 0x45, 0x57, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0a, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x5f, 0x49, + 0x4e, 0x49, 0x54, 0x10, 0x0a, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x44, 0x52, 0x41, + 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0b, 0x1a, 0x02, 0x08, 0x01, 0x12, + 0x17, 0x0a, 0x0f, 0x4c, 0x4f, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, + 0x53, 0x54, 0x10, 0x0c, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x41, 0x53, 0x54, + 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x10, 0x0d, 0x32, 0x41, 0x0a, + 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, + 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x10, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x11, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1126,19 +1238,20 @@ func file_message_proto_rawDescGZIP() []byte { } var file_message_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_message_proto_goTypes = []interface{}{ - (ServiceType)(0), // 0: message.ServiceType - (MessageType)(0), // 1: message.MessageType - (LotteryRequest_Type)(0), // 2: message.LotteryRequest.Type - (*Message)(nil), // 3: message.Message - (*Response)(nil), // 4: message.Response - (*LotteryResponse)(nil), // 5: message.LotteryResponse - (*LotteryRequest)(nil), // 6: message.LotteryRequest - (*StakingRequest)(nil), // 7: message.StakingRequest - (*ConsensusRequest)(nil), // 8: message.ConsensusRequest - (*DrandRequest)(nil), // 9: message.DrandRequest - (*ViewChangeRequest)(nil), // 10: message.ViewChangeRequest + (ServiceType)(0), // 0: message.ServiceType + (MessageType)(0), // 1: message.MessageType + (LotteryRequest_Type)(0), // 2: message.LotteryRequest.Type + (*Message)(nil), // 3: message.Message + (*Response)(nil), // 4: message.Response + (*LotteryResponse)(nil), // 5: message.LotteryResponse + (*LotteryRequest)(nil), // 6: message.LotteryRequest + (*StakingRequest)(nil), // 7: message.StakingRequest + (*ConsensusRequest)(nil), // 8: message.ConsensusRequest + (*DrandRequest)(nil), // 9: message.DrandRequest + (*LastSignPowerRequest)(nil), // 10: message.LastSignPowerRequest + (*ViewChangeRequest)(nil), // 11: message.ViewChangeRequest } var file_message_proto_depIdxs = []int32{ 0, // 0: message.Message.service_type:type_name -> message.ServiceType @@ -1146,19 +1259,20 @@ var file_message_proto_depIdxs = []int32{ 7, // 2: message.Message.staking:type_name -> message.StakingRequest 8, // 3: message.Message.consensus:type_name -> message.ConsensusRequest 9, // 4: message.Message.drand:type_name -> message.DrandRequest - 10, // 5: message.Message.viewchange:type_name -> message.ViewChangeRequest + 11, // 5: message.Message.viewchange:type_name -> message.ViewChangeRequest 6, // 6: message.Message.lottery_request:type_name -> message.LotteryRequest - 0, // 7: message.Response.service_type:type_name -> message.ServiceType - 1, // 8: message.Response.type:type_name -> message.MessageType - 5, // 9: message.Response.lottery_response:type_name -> message.LotteryResponse - 2, // 10: message.LotteryRequest.type:type_name -> message.LotteryRequest.Type - 3, // 11: message.ClientService.Process:input_type -> message.Message - 4, // 12: message.ClientService.Process:output_type -> message.Response - 12, // [12:13] is the sub-list for method output_type - 11, // [11:12] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 10, // 7: message.Message.last_sign_power:type_name -> message.LastSignPowerRequest + 0, // 8: message.Response.service_type:type_name -> message.ServiceType + 1, // 9: message.Response.type:type_name -> message.MessageType + 5, // 10: message.Response.lottery_response:type_name -> message.LotteryResponse + 2, // 11: message.LotteryRequest.type:type_name -> message.LotteryRequest.Type + 3, // 12: message.ClientService.Process:input_type -> message.Message + 4, // 13: message.ClientService.Process:output_type -> message.Response + 13, // [13:14] is the sub-list for method output_type + 12, // [12:13] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_message_proto_init() } @@ -1252,6 +1366,18 @@ func file_message_proto_init() { } } file_message_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LastSignPowerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_message_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ViewChangeRequest); i { case 0: return &v.state @@ -1270,6 +1396,7 @@ func file_message_proto_init() { (*Message_Drand)(nil), (*Message_Viewchange)(nil), (*Message_LotteryRequest)(nil), + (*Message_LastSignPower)(nil), } file_message_proto_msgTypes[1].OneofWrappers = []interface{}{ (*Response_LotteryResponse)(nil), @@ -1280,7 +1407,7 @@ func file_message_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_message_proto_rawDesc, NumEnums: 3, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/api/proto/message/message.proto b/api/proto/message/message.proto index 8bbf30f7c1..34e58a9176 100644 --- a/api/proto/message/message.proto +++ b/api/proto/message/message.proto @@ -29,6 +29,7 @@ enum MessageType { DRAND_INIT = 10 [deprecated=true]; DRAND_COMMIT = 11 [deprecated=true]; LOTTERY_REQUEST = 12 [deprecated=true]; // it should be either ENTER or GETPLAYERS but it will be removed later. + LAST_SIGN_POWER = 13; } // This is universal message for all communication protocols. @@ -47,6 +48,7 @@ message Message { ViewChangeRequest viewchange = 7; // Refactor this later after demo. LotteryRequest lottery_request = 8 [deprecated=true]; + LastSignPowerRequest last_sign_power = 9; } } @@ -98,6 +100,14 @@ message DrandRequest { bytes payload = 4 [deprecated=true]; } +message LastSignPowerRequest { + int64 prepare = 1; + int64 commit = 2; + int64 change = 3; + bytes sender_pubkey = 4; + uint32 shard_id = 5; +} + message ViewChangeRequest { uint64 view_id = 1; uint64 block_num = 2; diff --git a/consensus/consensus.go b/consensus/consensus.go index a281a8ae7c..14475d25ce 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -140,6 +140,9 @@ type Consensus struct { // Both flags only for initialization state. start bool isInitialLeader bool + + // value receives from + lastKnownSignPower int64 } // Blockchain returns the blockchain. @@ -399,6 +402,18 @@ func (consensus *Consensus) InitConsensusWithValidators() (err error) { return nil } +func (consensus *Consensus) SetLastKnownSignPower(i int64) { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + consensus.lastKnownSignPower = i +} + +func (consensus *Consensus) GetLastKnownSignPower() int64 { + consensus.mutex.RLock() + defer consensus.mutex.RUnlock() + return consensus.lastKnownSignPower +} + type downloadAsync struct { } diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index e92e242765..1cb44169c9 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" 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" consensus_engine "github.com/harmony-one/harmony/consensus/engine" "github.com/harmony-one/harmony/consensus/quorum" @@ -17,8 +18,10 @@ import ( bls_cosi "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/crypto/hash" "github.com/harmony-one/harmony/internal/chain" + nodeconfig "github.com/harmony-one/harmony/internal/configs/node" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/multibls" + "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard/committee" "github.com/harmony-one/harmony/webhooks" @@ -153,6 +156,47 @@ func (consensus *Consensus) updateBitmaps() { } +func (consensus *Consensus) sendLastSignPower() { + if consensus.isLeader() { + k, err := consensus.getLeaderPrivateKey(consensus.LeaderPubKey.Object) + if err != nil { + consensus.getLogger().Err(err).Msg("Leader not found in the committee") + return + } + comm, _ := consensus.decider.CurrentTotalPower(quorum.Commit) + prep, _ := consensus.decider.CurrentTotalPower(quorum.Prepare) + view, _ := consensus.decider.CurrentTotalPower(quorum.ViewChange) + msg := &msg_pb.Message{ + ServiceType: msg_pb.ServiceType_CONSENSUS, + Type: msg_pb.MessageType_LAST_SIGN_POWER, + Request: &msg_pb.Message_LastSignPower{ + LastSignPower: &msg_pb.LastSignPowerRequest{ + Prepare: getOrZero(prep), + Commit: getOrZero(comm), + Change: getOrZero(view), + SenderPubkey: k.Pub.Bytes[:], + ShardId: consensus.ShardID, + }, + }, + } + marshaledMessage, err := consensus.signAndMarshalConsensusMessage(msg, k.Pri) + if err != nil { + consensus.getLogger().Err(err). + Msg("[constructNewViewMessage] failed to sign and marshal the new view message") + return + } + msgToSend := proto.ConstructConsensusMessage(marshaledMessage) + if err := consensus.msgSender.SendWithoutRetry( + []nodeconfig.GroupID{ + nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, + p2p.ConstructMessage(msgToSend), + ); err != nil { + consensus.getLogger().Err(err). + Msg("[LastSignPower] could not send out the ViewChange message") + } + } +} + // ResetState resets the state of the consensus func (consensus *Consensus) resetState() { consensus.switchPhase("ResetState", FBFTAnnounce) @@ -160,6 +204,8 @@ func (consensus *Consensus) resetState() { consensus.blockHash = [32]byte{} consensus.block = []byte{} consensus.decider.ResetPrepareAndCommitVotes() + consensus.sendLastSignPower() + if consensus.prepareBitmap != nil { consensus.prepareBitmap.Clear() } diff --git a/consensus/consensus_v2.go b/consensus/consensus_v2.go index 6caed6e504..b9a93b9fcb 100644 --- a/consensus/consensus_v2.go +++ b/consensus/consensus_v2.go @@ -20,6 +20,7 @@ import ( vrf_bls "github.com/harmony-one/harmony/crypto/vrf/bls" nodeconfig "github.com/harmony-one/harmony/internal/configs/node" "github.com/harmony-one/harmony/internal/utils" + "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/shard" "github.com/harmony-one/vdf/src/vdf_go" @@ -90,6 +91,8 @@ func (consensus *Consensus) HandleMessageUpdate(ctx context.Context, peer libp2p case t == msg_pb.MessageType_NEWVIEW: members := consensus.decider.Participants() fbftMsg, err = ParseNewViewMessage(msg, members) + case t == msg_pb.MessageType_LAST_SIGN_POWER: + return nil default: fbftMsg, err = consensus.parseFBFTMessage(msg) } @@ -971,3 +974,10 @@ func (consensus *Consensus) DeleteMessagesLessThan(number uint64) { defer consensus.mutex.Unlock() consensus.fBFTLog.deleteMessagesLessThan(number) } + +func getOrZero(n *numeric.Dec) int64 { + if n == nil { + return 0 + } + return (*n).Mul(numeric.NewDec(100)).TruncateInt64() +} diff --git a/consensus/fbft_log.go b/consensus/fbft_log.go index cec74e314b..60c4d248e1 100644 --- a/consensus/fbft_log.go +++ b/consensus/fbft_log.go @@ -36,6 +36,7 @@ type FBFTMessage struct { M3AggSig *bls_core.Sign M3Bitmap *bls_cosi.Mask Verified bool + LastVotePower int64 } func (m *FBFTMessage) Hash() []byte { diff --git a/node/api.go b/node/api.go index d49d40f076..4df6a8ffc8 100644 --- a/node/api.go +++ b/node/api.go @@ -2,9 +2,7 @@ package node import ( "github.com/harmony-one/harmony/consensus/quorum" - "github.com/harmony-one/harmony/consensus/votepower" "github.com/harmony-one/harmony/core/types" - "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/eth/rpc" "github.com/harmony-one/harmony/hmy" "github.com/harmony-one/harmony/internal/tikv" @@ -181,27 +179,7 @@ func (node *Node) GetLastSigningPower() (float64, error) { } func (node *Node) GetLastSigningPower2() (float64, error) { - bc := node.Consensus.Blockchain() - cur := bc.CurrentBlock() - ss, err := bc.ReadShardState(cur.Epoch()) - if err != nil { - return 0, err - } - roster, err := votepower.Compute(&ss.Shards[bc.ShardID()], cur.Epoch()) - if err != nil { - return 0, err - } - blsPubKeys, err := ss.Shards[bc.ShardID()].BLSPublicKeys() - if err != nil { - return 0, err - } - - mask := bls.NewMask(blsPubKeys) - err = mask.SetMask(cur.Header().LastCommitBitmap()) - if err != nil { - return 0, err - } - power := roster.VotePowerByMask(mask) - round := float64(power.MulInt64(10000).RoundInt64()) / 10000 + p := node.Consensus.GetLastKnownSignPower() + round := float64(p) / 10000 return round, nil } diff --git a/node/node.go b/node/node.go index 846eaecebb..a007b7ab0c 100644 --- a/node/node.go +++ b/node/node.go @@ -471,12 +471,14 @@ func (node *Node) validateNodeMessage(ctx context.Context, payload []byte) ( return payload[p2pNodeMsgPrefixSize:], msgType, nil } +type ignore = bool + // validateShardBoundMessage validate consensus message // validate shardID // validate public key size // verify message signature func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer.ID, nodeConfig *nodeconfig.ConfigType, payload []byte, -) (*msg_pb.Message, *bls.SerializedPublicKey, bool, error) { +) (*msg_pb.Message, *bls.SerializedPublicKey, ignore, error) { var ( m msg_pb.Message //consensus = registry.GetConsensus() @@ -528,11 +530,16 @@ func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer. } } - maybeCon, maybeVC := m.GetConsensus(), m.GetViewchange() - senderKey := []byte{} - senderBitmap := []byte{} + var ( + maybeCon = m.GetConsensus() + maybeVC = m.GetViewchange() + maybeSP = m.GetLastSignPower() + senderKey []byte + senderBitmap []byte + ) - if maybeCon != nil { + switch { + case maybeCon != nil: if maybeCon.ShardId != consensus.ShardID { nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid_shard"}).Inc() return nil, nil, true, errors.WithStack(errWrongShardID) @@ -546,7 +553,7 @@ func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer. if maybeCon.ViewId+5 < consensus.GetCurBlockViewID() { return nil, nil, true, errors.WithStack(errViewIDTooOld) } - } else if maybeVC != nil { + case maybeVC != nil: if maybeVC.ShardId != consensus.ShardID { nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid_shard"}).Inc() return nil, nil, true, errors.WithStack(errWrongShardID) @@ -556,7 +563,14 @@ func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer. if maybeVC.ViewId+5 < consensus.GetViewChangingID() { return nil, nil, true, errors.WithStack(errViewIDTooOld) } - } else { + case maybeSP != nil: + if maybeSP.ShardId != consensus.ShardID { + nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid_shard"}).Inc() + return nil, nil, true, errors.WithStack(errWrongShardID) + } + senderKey = maybeSP.SenderPubkey + consensus.SetLastKnownSignPower(maybeSP.Commit) + default: nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid"}).Inc() return nil, nil, true, errors.WithStack(errNoSenderPubKey) } From 8070f87e000ef0f46c08f58be34f0f0a9c9f68a4 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:44:09 -0400 Subject: [PATCH 46/66] Fixed panic. --- consensus/votepower/roster.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/consensus/votepower/roster.go b/consensus/votepower/roster.go index 96a3ac9c6b..80380c9ca8 100644 --- a/consensus/votepower/roster.go +++ b/consensus/votepower/roster.go @@ -201,7 +201,11 @@ func Compute(subComm *shard.Committee, epoch *big.Int) (*Roster, error) { } else { // Our node member.IsHarmonyNode = true member.OverallPercent = harmonyPercent.Quo(asDecHMYSlotCount) - member.GroupPercent = member.OverallPercent.Quo(harmonyPercent) + if member.OverallPercent.IsZero() { + member.GroupPercent = member.OverallPercent.Copy() + } else { + member.GroupPercent = member.OverallPercent.Quo(harmonyPercent) + } ourPercentage = ourPercentage.Add(member.OverallPercent) } From c126c6184c45652b2989af6963d97fcc785edb33 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 25 Jun 2024 19:44:16 -0400 Subject: [PATCH 47/66] Tests. --- .travis.yml | 1 - scripts/travis_rpc_checker.sh | 9 +- tests/Dockerfile | 51 + tests/Makefile | 44 + tests/README.md | 73 + ...a95a43125cd16c4f79dd1d505a5eb6a22e7c8a.key | 1 + ...6a4f5e048e6d8b8a000d77a478d44cd640270c.key | 1 + ...ad1e86dce7458b1c295404fb54a0d61e50bb97.key | 1 + ...237710e0a4beda8adeaefde4844ab4c4b2bf98.key | 1 + tests/configs/localnet_deploy.config | 27 + tests/configs/localnet_rosetta_test_s0.json | 471 +++++ tests/configs/localnet_rosetta_test_s1.json | 319 +++ tests/requirements.txt | 5 + tests/rpc_tests/conftest.py | 53 + tests/rpc_tests/test_account.py | 261 +++ tests/rpc_tests/test_blockchain.py | 783 +++++++ tests/rpc_tests/test_contract.py | 173 ++ tests/rpc_tests/test_staking.py | 1796 +++++++++++++++++ tests/rpc_tests/test_transaction.py | 788 ++++++++ tests/rpc_tests/txs.py | 404 ++++ tests/rpc_tests/utils.py | 133 ++ tests/scripts/release_test.sh | 9 + tests/scripts/run.sh | 226 +++ 23 files changed, 5623 insertions(+), 7 deletions(-) create mode 100644 tests/Dockerfile create mode 100644 tests/Makefile create mode 100644 tests/README.md create mode 100644 tests/configs/1ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8a.key create mode 100644 tests/configs/4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c.key create mode 100644 tests/configs/5a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97.key create mode 100644 tests/configs/5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98.key create mode 100644 tests/configs/localnet_deploy.config create mode 100644 tests/configs/localnet_rosetta_test_s0.json create mode 100644 tests/configs/localnet_rosetta_test_s1.json create mode 100644 tests/requirements.txt create mode 100644 tests/rpc_tests/conftest.py create mode 100644 tests/rpc_tests/test_account.py create mode 100644 tests/rpc_tests/test_blockchain.py create mode 100644 tests/rpc_tests/test_contract.py create mode 100644 tests/rpc_tests/test_staking.py create mode 100644 tests/rpc_tests/test_transaction.py create mode 100644 tests/rpc_tests/txs.py create mode 100644 tests/rpc_tests/utils.py create mode 100644 tests/scripts/release_test.sh create mode 100644 tests/scripts/run.sh diff --git a/.travis.yml b/.travis.yml index 7d28d68d61..1a14a60c3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,6 @@ install: - echo $TRAVIS_PULL_REQUEST_BRANCH - git clone https://github.com/harmony-one/mcl.git $GOPATH/src/github.com/harmony-one/mcl - git clone https://github.com/harmony-one/bls.git $GOPATH/src/github.com/harmony-one/bls - - git clone https://github.com/harmony-one/harmony-test.git $GOPATH/src/github.com/harmony-one/harmony-test - (cd $GOPATH/src/github.com/harmony-one/mcl; make -j4) - (cd $GOPATH/src/github.com/harmony-one/bls; make BLS_SWAP_G=1 -j4) # - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.41.1 diff --git a/scripts/travis_rpc_checker.sh b/scripts/travis_rpc_checker.sh index 5de2ef93b8..ada3f986db 100755 --- a/scripts/travis_rpc_checker.sh +++ b/scripts/travis_rpc_checker.sh @@ -5,11 +5,8 @@ echo $TRAVIS_PULL_REQUEST_BRANCH DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo $DIR echo $GOPATH -cd $GOPATH/src/github.com/harmony-one/harmony-test -git fetch -git checkout $TRAVIS_PULL_REQUEST_BRANCH || true -git pull -git branch --show-current -cd localnet +cd tests +echo "$DIR/../:/go/src/github.com/harmony-one/harmony" docker build -t harmonyone/localnet-test . + docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -n \ No newline at end of file diff --git a/tests/Dockerfile b/tests/Dockerfile new file mode 100644 index 0000000000..cac0b755e8 --- /dev/null +++ b/tests/Dockerfile @@ -0,0 +1,51 @@ +FROM golang:1.19 + +WORKDIR $GOPATH/src/github.com/harmony-one + +SHELL ["/bin/bash", "-c"] + +# These are split into multiple lines to allow debugging the error message that I cannot reproduce locally +# The command `xxx` returned a non-zero code: 100 +RUN apt clean > /dev/null 2>1 +RUN apt update > /dev/null 2>1 +RUN apt upgrade -y > /dev/null 2>1 +RUN apt update -y > /dev/null 2>1 +RUN apt install -y unzip libgmp-dev libssl-dev curl git jq make gcc g++ bash sudo python3 python3-pip > /dev/null 2>1 + +RUN git clone https://github.com/harmony-one/harmony.git > /dev/null 2>1 \ + && git clone https://github.com/harmony-one/bls.git > /dev/null 2>1 \ + && git clone https://github.com/harmony-one/mcl.git > /dev/null 2>1 + +# Fix complaints about Docker / root / user ownership for Golang "VCS stamping" +# https://github.com/golang/go/blob/3900ba4baf0e3b309a55b5ac4dd25f709df09772/src/cmd/go/internal/vcs/vcs.go +RUN git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/harmony > /dev/null 2>1 \ + && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/bls > /dev/null 2>1 \ + && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/mcl > /dev/null 2>1 + +# Build to fetch all dependencies for faster test builds +RUN cd harmony > /dev/null 2>1 && go mod tidy > /dev/null 2>1 && go get github.com/pborman/uuid > /dev/null 2>1 && go get github.com/rjeczalik/notify > /dev/null 2>1 \ + && go get github.com/cespare/cp > /dev/null 2>1 && go get github.com/libp2p/go-libp2p-crypto > /dev/null 2>1 && go get github.com/kr/pretty > /dev/null 2>1 \ + && go get github.com/kr/text > /dev/null 2>1 && go get gopkg.in/check.v1 > /dev/null 2>1 && bash scripts/install_build_tools.sh > /dev/null 2>1 && make > /dev/null 2>1 +RUN rm -rf harmony + +# Install testing tools +RUN curl -L -o /go/bin/hmy https://harmony.one/hmycli > /dev/null 2>1 && chmod +x /go/bin/hmy > /dev/null 2>1 + +WORKDIR $GOPATH/src/github.com/coinbase + +RUN git clone https://github.com/coinbase/rosetta-cli.git > /dev/null 2>1 +RUN cd rosetta-cli && make install > /dev/null 2>1 + +WORKDIR $GOPATH/src/github.com/harmony-one/harmony-test/localnet + +COPY scripts scripts +COPY rpc_tests rpc_tests +COPY configs configs +COPY requirements.txt requirements.txt + +# Since we are running as root in Docker, `--break-system-packages` is required +RUN python3 -m pip install -r requirements.txt --break-system-packages > /dev/null 2>1 && rm requirements.txt +RUN chmod +x $GOPATH/src/github.com/harmony-one/harmony-test/localnet/scripts/run.sh + +WORKDIR $GOPATH/src/github.com/harmony-one/harmony +ENTRYPOINT ["/go/src/github.com/harmony-one/harmony-test/localnet/scripts/run.sh"] diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000000..86c439753f --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,44 @@ +.PHONY: install build build-cached upload upload-test test-docker help run + +help: + @echo "install - install dependencies for running tests without docker" + @echo "build - build the docker image" + @echo "build-cached - build the docker image with cache" + @echo "upload-test - test the docker image before uploading to dockerhub" + @echo "upload - upload the docker image to dockerhub (require credentials)" + @echo "test - run all localnet tests as it would run inside the docker container" + @echo "test-docker - run all localnet tests inside the docker container" + @echo "rosetta-test-run - run the rosetta tests as it would run inside the docker container" + @echo "rpc-test-run - run the localnet rpc tests as it would run inside the docker container" + @echo "rpc-test-debug - run the rpc test suite on a running localnet" + +install: + python3 -m pip install -r requirements.txt + +build: + docker build --pull -t harmonyone/localnet-test . --no-cache + +build-cached: + docker build -t harmonyone/localnet-test . + +upload-test: build + bash ./scripts/release_test.sh + +upload: + docker push harmonyone/localnet-test + +test: + bash ./scripts/run.sh -k + +test-docker: + docker run --name harmony-tests --rm -it -v "$(shell go env GOPATH)"/src/github.com/harmony-one/harmony:/go/src/github.com/harmony-one/harmony harmonyone/localnet-test + +rosetta-test-run: + bash ./scripts/run.sh -r -k + +rpc-test-run: + bash ./scripts/run.sh -n -k + +rpc-test-debug: + python3 -u -m py.test -v -r s -s rpc_tests -x -n 8 + diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000000..244d36c47e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,73 @@ +# Localnet tests + +Tools wrapped in a Dockerfile to **build**, **deploy** and **test** a localnet. + +## Assumptions +* The main harmony repo follows the GO-PATH convention. So the path to said repo must be: +```bash +$(go env GOPATH)/src/github.com/harmony-one/harmony +``` +* This repo follows the GO-PATH convention. So the path to said repo must be: +```bash +$(go env GOPATH)/src/github.com/harmony-one/harmony-test +``` +* No extra transactions on the localnet are done prior to running the pytest in `./tests` or execution of the rosetta integration test. +* The localnet faucet address is `one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur` + +## Requirements (dev testing - no docker) +* Go +* jq +* Python 3.6+ +* Pip3 +* Python lib requirements from `requirements.txt` +> You can install the libs with the following command: `make install` +* The [rosetta-cli](https://github.com/coinbase/rosetta-cli) installed & on path (`$PATH`) + +## Create a python venv +> This step is **optional** but *recommended* to not pollute your local Python installation. +``` + python3 -m venv .venv + source .venv/bin/activate +``` + +## Build & run tests +* To build the docker image locally, do: +```bash +make build +``` +* If you wish to build the docker image with a custom tag, do: +```bash +docker build -t "$TAG_NAME" . +``` +> Note that you have to be in the same directory as the `Dockerfile` + +* To release the docker image to Dockerhub, do: +```bash +make upload +``` + +* To run the test (start localnet, test, and teardown) outside of the docker image (for dev testing), do: +```bash +make test +``` +> This will test whatever is in the main repo (following GO-PATH convention). + +* To run the localnet tests with docker using your local harmony repository, do: +```bash +make test-docker +``` + +> This will test whatever is in the main repo (following GO-PATH convention). + +## Release + +To release the docker image (used by PR test & main repo), first make sure it passes the release test: +```bash +make upload-test +``` +> This will run the tests, wrapped in a docker img, 10 times and expects all 10 times to be successful. + +Then upload with (assuming you have proper docker-hub credentials): +```bash +make upload +``` diff --git a/tests/configs/1ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8a.key b/tests/configs/1ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8a.key new file mode 100644 index 0000000000..0014f5069f --- /dev/null +++ b/tests/configs/1ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8a.key @@ -0,0 +1 @@ +61a55754a1cf13789f97f573d952ef23c0ee2f73702ad1fd8233aabe858bd379efd69dc6420eee99b6c7d50d68d285248852e88ea500c8063897559455b9f1008aea686caaeeb05c6b1f1a4a46d1353c20d09d4348f1f4aa1c306631 \ No newline at end of file diff --git a/tests/configs/4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c.key b/tests/configs/4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c.key new file mode 100644 index 0000000000..77581cba0b --- /dev/null +++ b/tests/configs/4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c.key @@ -0,0 +1 @@ +a010bc1550956a3a4935cdc6f8633ea770bd0321094cfaccd25d3ea3b5382417cb5c150de0357ee8b6eeeec135ae0ec379701c7f35ae33da9030e93a630dc3a988577d1a1b0a9e60976f79d5cefa68123ac77c636f2ccab149fc8fc7 \ No newline at end of file diff --git a/tests/configs/5a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97.key b/tests/configs/5a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97.key new file mode 100644 index 0000000000..ae7af7f0ee --- /dev/null +++ b/tests/configs/5a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97.key @@ -0,0 +1 @@ +e176a1a8d9c533ad7efbaa9caca1d839146495683f669be35dddfebe2f39497c73fc2a6d7da116acd3698f582fcfe6b7b9fc18fd286a42bcdf007dc7a618bab958eb5c97f6082104ff723705d36744289b9885a692c01731cb45c698 \ No newline at end of file diff --git a/tests/configs/5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98.key b/tests/configs/5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98.key new file mode 100644 index 0000000000..1708e08a8b --- /dev/null +++ b/tests/configs/5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98.key @@ -0,0 +1 @@ +97073dbd1cf59aa458f6e58504e633b74982be646ba9e863611ade28f07a651b7371713406b0756137d6a19452254f6b92636956db1c864c66f1a4cf8acf5711791c1598e8e45080cd0c479035a937894444126bc92ceb3b220d0378 \ No newline at end of file diff --git a/tests/configs/localnet_deploy.config b/tests/configs/localnet_deploy.config new file mode 100644 index 0000000000..f8a8bce81e --- /dev/null +++ b/tests/configs/localnet_deploy.config @@ -0,0 +1,27 @@ +127.0.0.1 9000 validator .hmy/65f55eb3052f9e9f632b2923be594ba77c55543f5c58ee1454b9cfd658d25e06373b0f7d42a19c84768139ea294f6204.key +127.0.0.1 9002 validator .hmy/40379eed79ed82bebfb4310894fd33b6a3f8413a78dc4d43b98d0adc9ef69f3285df05eaab9f2ce5f7227f8cb920e809.key +127.0.0.1 9004 validator .hmy/02c8ff0b88f313717bc3a627d2f8bb172ba3ad3bb9ba3ecb8eed4b7c878653d3d4faf769876c528b73f343967f74a917.key +127.0.0.1 9006 validator .hmy/ee2474f93cba9241562efc7475ac2721ab0899edf8f7f115a656c0c1f9ef8203add678064878d174bb478fa2e6630502.key +127.0.0.1 9008 validator .hmy/e751ec995defe4931273aaebcb2cd14bf37e629c554a57d3f334c37881a34a6188a93e76113c55ef3481da23b7d7ab09.key +127.0.0.1 9010 validator .hmy/776f3b8704f4e1092a302a60e84f81e476c212d6f458092b696df420ea19ff84a6179e8e23d090b9297dc041600bc100.key +127.0.0.1 9012 validator .hmy/2d61379e44a772e5757e27ee2b3874254f56073e6bd226eb8b160371cc3c18b8c4977bd3dcb71fd57dc62bf0e143fd08.key +127.0.0.1 9014 validator .hmy/c4e4708b6cf2a2ceeb59981677e9821eebafc5cf483fb5364a28fa604cc0ce69beeed40f3f03815c9e196fdaec5f1097.key +127.0.0.1 9016 validator .hmy/86dc2fdc2ceec18f6923b99fd86a68405c132e1005cf1df72dca75db0adfaeb53d201d66af37916d61f079f34f21fb96.key +127.0.0.1 9018 validator .hmy/49d15743b36334399f9985feb0753430a2b287b2d68b84495bbb15381854cbf01bca9d1d9f4c9c8f18509b2bfa6bd40f.key +127.0.0.1 9020 validator .hmy/95117937cd8c09acd2dfae847d74041a67834ea88662a7cbed1e170350bc329e53db151e5a0ef3e712e35287ae954818.key +127.0.0.1 9022 validator .hmy/68ae289d73332872ec8d04ac256ca0f5453c88ad392730c5741b6055bc3ec3d086ab03637713a29f459177aaa8340615.key +127.0.0.1 9024 external ../harmony-test/localnet/configs/4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c.key +127.0.0.1 9098 explorer null 0 + +127.0.0.1 9100 validator .hmy/52ecce5f64db21cbe374c9268188f5d2cdd5bec1a3112276a350349860e35fb81f8cfe447a311e0550d961cf25cb988d.key +127.0.0.1 9102 validator .hmy/a547a9bf6fdde4f4934cde21473748861a3cc0fe8bbb5e57225a29f483b05b72531f002f8187675743d819c955a86100.key +127.0.0.1 9104 validator .hmy/678ec9670899bf6af85b877058bea4fc1301a5a3a376987e826e3ca150b80e3eaadffedad0fedfa111576fa76ded980c.key +127.0.0.1 9106 validator .hmy/63f479f249c59f0486fda8caa2ffb247209489dae009dfde6144ff38c370230963d360dffd318cfb26c213320e89a512.key +127.0.0.1 9108 validator .hmy/16513c487a6bb76f37219f3c2927a4f281f9dd3fd6ed2e3a64e500de6545cf391dd973cc228d24f9bd01efe94912e714.key +127.0.0.1 9110 validator .hmy/576d3c48294e00d6be4a22b07b66a870ddee03052fe48a5abbd180222e5d5a1f8946a78d55b025de21635fd743bbad90.key +127.0.0.1 9112 validator .hmy/eca09c1808b729ca56f1b5a6a287c6e1c3ae09e29ccf7efa35453471fcab07d9f73cee249e2b91f5ee44eb9618be3904.key +127.0.0.1 9114 validator .hmy/f47238daef97d60deedbde5302d05dea5de67608f11f406576e363661f7dcbc4a1385948549b31a6c70f6fde8a391486.key +127.0.0.1 9116 validator .hmy/fc4b9c535ee91f015efff3f32fbb9d32cdd9bfc8a837bb3eee89b8fff653c7af2050a4e147ebe5c7233dc2d5df06ee0a.key +127.0.0.1 9118 validator .hmy/ca86e551ee42adaaa6477322d7db869d3e203c00d7b86c82ebee629ad79cb6d57b8f3db28336778ec2180e56a8e07296.key +127.0.0.1 9120 external ../harmony-test/localnet/configs/5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98.key +127.0.0.1 9096 explorer null 1 \ No newline at end of file diff --git a/tests/configs/localnet_rosetta_test_s0.json b/tests/configs/localnet_rosetta_test_s0.json new file mode 100644 index 0000000000..9421780115 --- /dev/null +++ b/tests/configs/localnet_rosetta_test_s0.json @@ -0,0 +1,471 @@ +{ + "network": { + "blockchain": "Harmony", + "network": "Testnet", + "sub_network_identifier": { + "network": "shard 0", + "metadata": { + "is_beacon": true + } + } + }, + "online_url": "http://localhost:9798", + "http_timeout": 300, + "max_retries": 0, + "retry_elapsed_time": 5, + "max_online_connections": 0, + "max_sync_concurrency": 0, + "tip_delay": 360, + "log_configuration": false, + "data": { + "active_reconciliation_concurrency": 0, + "inactive_reconciliation_concurrency": 0, + "inactive_reconciliation_frequency": 0, + "log_blocks": false, + "log_transactions": false, + "log_balance_changes": false, + "log_reconciliations": false, + "ignore_reconciliation_error": false, + "exempt_accounts": "", + "bootstrap_balances": "", + "interesting_accounts": "", + "reconciliation_disabled": false, + "inactive_discrepancy_search_disabled": false, + "balance_tracking_disabled": false, + "coin_tracking_disabled": false, + "end_conditions": { + "duration": 20, + "reconciliation_coverage": { + "coverage": 0.95, + "from_tip": true + } + }, + "results_output_file": "" + }, + "construction": { + "offline_url": "http://localhost:9798", + "max_offline_connections": 1, + "stale_depth": 0, + "broadcast_limit": 0, + "ignore_broadcast_failures": false, + "clear_broadcasts": false, + "broadcast_behind_tip": false, + "block_broadcast_limit": 0, + "rebroadcast_all": false, + "prefunded_accounts": [ + { + "privkey": "1f84c95ac16e6a50f08d44c7bde7aff8742212fda6e4321fde48bf83bef266dc", + "account_identifier": { + "address": "one155jp2y76nazx8uw5sa94fr0m4s5aj8e5xm6fu3", + "metadata": { + "hex_address": "0xA5241513DA9F4463F1d4874b548dFBAC29D91f34" + } + }, + "curve_type": "secp256k1", + "currency": { + "symbol": "ONE", + "decimals": 18 + } + } + ], + "workflows": [ + { + "name": "request_funds", + "concurrency": 1, + "scenarios": [ + { + "name": "find_account", + "actions": [ + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\":1}", + "type": "find_balance", + "output_path": "random_account" + } + ] + }, + { + "name": "request", + "actions": [ + { + "input": "{\"account_identifier\": {{random_account.account_identifier}}, \"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "loaded_account" + } + ] + } + ] + }, + { + "name": "create_account", + "concurrency": 1, + "scenarios": [ + { + "name": "create_account", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "network" + }, + { + "input": "{\"curve_type\": \"secp256k1\"}", + "type": "generate_key", + "output_path": "key" + }, + { + "input": "{\"network_identifier\": {{network}}, \"public_key\": {{key.public_key}}}", + "type": "derive", + "output_path": "account" + }, + { + "input": "{\"account_identifier\": {{account.account_identifier}}, \"keypair\": {{key}}}", + "type": "save_account" + } + ] + } + ] + }, + { + "name": "transfer", + "concurrency": 1, + "scenarios": [ + { + "name": "transfer", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "transfer.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"53000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": {{sender.balance.value}}, \"right_value\": {{max_fee}}}", + "type": "math", + "output_path": "available_amount" + }, + { + "input": "{\"minimum\": \"1\", \"maximum\": {{available_amount}}}", + "type": "random_number", + "output_path": "recipient_amount" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": \"0\", \"right_value\":{{recipient_amount}}}", + "type": "math", + "output_path": "sender_amount" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "transfer.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"NativeTransfer\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":{{sender_amount}},\"currency\":{{currency}}}},{\"operation_identifier\":{\"index\":1},\"related_operations\":[{\"index\":0}],\"type\":\"NativeTransfer\",\"account\":{{recipient.account_identifier}},\"amount\":{\"value\":{{recipient_amount}},\"currency\":{{currency}}}}]", + "type": "set_variable", + "output_path": "transfer.operations" + } + ] + } + ] + }, + { + "name": "cross_shard_transfer", + "concurrency": 10, + "scenarios": [ + { + "name": "transfer", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "transfer.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"53000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": {{sender.balance.value}}, \"right_value\": {{max_fee}}}", + "type": "math", + "output_path": "available_amount" + }, + { + "input": "{\"minimum\": \"1\", \"maximum\": {{available_amount}}}", + "type": "random_number", + "output_path": "recipient_amount" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": \"0\", \"right_value\":{{recipient_amount}}}", + "type": "math", + "output_path": "sender_amount" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "transfer.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"NativeCrossShardTransfer\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":{{sender_amount}},\"currency\":{{currency}}}, \"metadata\":{\"from\":{{sender.account_identifier}}, \"to\": {{recipient.account_identifier}}}}]", + "type": "set_variable", + "output_path": "transfer.operations" + }, + { + "input": "{\"to_shard\":1, \"from_shard\":0}", + "type": "set_variable", + "output_path": "transfer.preprocess_metadata" + } + ] + } + ] + }, + { + "name": "contract_creation", + "concurrency": 10, + "scenarios": [ + { + "name": "transfer", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "transfer.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"530000000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "transfer.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"ContractCreation\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":\"0\",\"currency\":{{currency}}}}]", + "type": "set_variable", + "output_path": "transfer.operations" + }, + { + "input": "{\"data\": \"0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061019c806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a723158209b80813a158b44af65aee232b44c0ac06472c48f4abbe298852a39f0ff34a9f264736f6c63430005100032\"}", + "type": "set_variable", + "output_path": "transfer.preprocess_metadata" + } + ] + } + ] + }, + { + "name": "staking", + "concurrency": 1, + "scenarios": [ + { + "name": "create_validator", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "create_validator.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"200000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"20000000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "{{sender.account_identifier.address}}", + "type": "set_variable", + "output_path": "validator_address" + }, + { + "input": "{{sender.account_identifier}}", + "type": "set_variable", + "output_path": "validator_account_identifier" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "create_validator.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"CreateValidator\",\"status\":\"\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":\"-30000000000000000000000\",\"currency\":{\"symbol\":\"ONE\",\"decimals\":18}},\"Metadata\":{\"validatorAddress\":{{sender.account_identifier.address}},\"commissionRate\":100000000000000000,\"maxCommissionRate\":900000000000000000,\"maxChangeRate\":50000000000000000,\"minSelfDelegation\":20000,\"maxTotalDelegation\":50000,\"amount\":30000,\"name\":\"Alice\",\"website\":\"alice.harmony.one\",\"identity\":\"alice\",\"securityContact\":\"Bob\",\"details\":\"Don't mess with me!!!\"}}]", + "type": "set_variable", + "output_path": "create_validator.operations" + }, + { + "input": "{\"from_shard\":0,\"to_shard\":0,\"slot_pub_keys\":[\"0x30b2c38b1316da91e068ac3bd8751c0901ef6c02a1d58bc712104918302c6ed03d5894671d0c816dad2b4d303320f202\"],\"slot_key_sigs\":[\"0x68f800b6adf657b674903e04708060912b893b7c7b500788808247550ab3e186e56a44ebf3ca488f8ed1a42f6cef3a04bd5d2b2b7eb5a767848d3135b362e668ce6bba42c7b9d5666d8e3a83be707b5708e722c58939fe9b07c170f3b7062414\"]}", + "type": "set_variable", + "output_path": "create_validator.preprocess_metadata" + } + ] + }, + { + "name": "edit_validator", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "edit_validator.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"200000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"20000000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "edit_validator.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"EditValidator\",\"status\":\"\",\"account\":{{validator_account_identifier}},\"amount\":{\"value\":\"0\",\"currency\":{\"symbol\":\"ONE\",\"decimals\":18}},\"Metadata\":{\"validatorAddress\":{{validator_address}},\"commissionRate\":100000000000000000,\"minSelfDelegation\":20000,\"maxTotalDelegation\":50000,\"name\":\"Alice\",\"website\":\"alice.harmony.one\",\"identity\":\"alice\",\"securityContact\":\"Bob\",\"details\":\"Don't mess with me!!!\"}}]", + "type": "set_variable", + "output_path": "edit_validator.operations" + }, + { + "input": "{\"from_shard\":0,\"to_shard\":0,\"slot_pub_key_to_add\":\"0x30b2c38b1316da91e068ac3bd8751c0901ef6c02a1d58bc712104918302c6ed03d5894671d0c816dad2b4d303320f202\",\"slot_pub_key_to_remove\":\"0x30b2c38b1316da91e068ac3bd8751c0901ef6c02a1d58bc712104918302c6ed03d5894671d0c816dad2b4d303320f202\",\"slot_key_to_add_sig\":\"0x68f800b6adf657b674903e04708060912b893b7c7b500788808247550ab3e186e56a44ebf3ca488f8ed1a42f6cef3a04bd5d2b2b7eb5a767848d3135b362e668ce6bba42c7b9d5666d8e3a83be707b5708e722c58939fe9b07c170f3b7062414\"}", + "type": "set_variable", + "output_path": "edit_validator.preprocess_metadata" + } + ] + }, + { + "name": "delegate", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 0\", \"metadata\":{\"is_beacon\": true}}}", + "type": "set_variable", + "output_path": "delegate.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"200000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"20000000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "delegate.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"Delegate\",\"status\":\"\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":\"-1000000000000000000000\",\"currency\":{\"symbol\":\"ONE\",\"decimals\":18}},\"Metadata\":{\"validatorAddress\":{{validator_address}},\"delegatorAddress\":{{sender.account_identifier.address}},\"amount\":1000}}]", + "type": "set_variable", + "output_path": "delegate.operations" + }, + { + "input": "{\"from_shard\":0,\"to_shard\":0}", + "type": "set_variable", + "output_path": "delegate.preprocess_metadata" + } + ] + } + ] + } + ], + "end_conditions": { + "create_account": 1, + "transfer": 1, + "cross_shard_transfer": 1, + "contract_creation": 1, + "staking": 1 + } + } +} diff --git a/tests/configs/localnet_rosetta_test_s1.json b/tests/configs/localnet_rosetta_test_s1.json new file mode 100644 index 0000000000..1792d09fe5 --- /dev/null +++ b/tests/configs/localnet_rosetta_test_s1.json @@ -0,0 +1,319 @@ +{ + "network": { + "blockchain": "Harmony", + "network": "Testnet", + "sub_network_identifier": { + "network": "shard 1", + "metadata": { + "is_beacon": false + } + } + }, + "online_url": "http://localhost:9796", + "http_timeout": 300, + "max_retries": 0, + "retry_elapsed_time": 5, + "max_online_connections": 0, + "max_sync_concurrency": 0, + "tip_delay": 360, + "log_configuration": false, + "data": { + "active_reconciliation_concurrency": 0, + "inactive_reconciliation_concurrency": 0, + "inactive_reconciliation_frequency": 0, + "log_blocks": false, + "log_transactions": false, + "log_balance_changes": false, + "log_reconciliations": false, + "ignore_reconciliation_error": false, + "exempt_accounts": "", + "bootstrap_balances": "", + "interesting_accounts": "", + "reconciliation_disabled": false, + "inactive_discrepancy_search_disabled": false, + "balance_tracking_disabled": false, + "coin_tracking_disabled": false, + "end_conditions": { + "duration": 20, + "reconciliation_coverage": { + "coverage": 0.95, + "from_tip": true + } + }, + "results_output_file": "" + }, + "construction": { + "offline_url": "http://localhost:9796", + "max_offline_connections": 1, + "stale_depth": 0, + "broadcast_limit": 0, + "ignore_broadcast_failures": false, + "clear_broadcasts": false, + "broadcast_behind_tip": false, + "block_broadcast_limit": 0, + "rebroadcast_all": false, + "prefunded_accounts": [ + { + "privkey": "1f84c95ac16e6a50f08d44c7bde7aff8742212fda6e4321fde48bf83bef266dc", + "account_identifier": { + "address": "one155jp2y76nazx8uw5sa94fr0m4s5aj8e5xm6fu3", + "metadata": { + "hex_address": "0xA5241513DA9F4463F1d4874b548dFBAC29D91f34" + } + }, + "curve_type": "secp256k1", + "currency": { + "symbol": "ONE", + "decimals": 18 + } + } + ], + "workflows": [ + { + "name": "request_funds", + "concurrency": 1, + "scenarios": [ + { + "name": "find_account", + "actions": [ + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\":1}", + "type": "find_balance", + "output_path": "random_account" + } + ] + }, + { + "name": "request", + "actions": [ + { + "input": "{\"account_identifier\": {{random_account.account_identifier}}, \"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "loaded_account" + } + ] + } + ] + }, + { + "name": "create_account", + "concurrency": 1, + "scenarios": [ + { + "name": "create_account", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 1\", \"metadata\":{\"is_beacon\": false}}}", + "type": "set_variable", + "output_path": "network" + }, + { + "input": "{\"curve_type\": \"secp256k1\"}", + "type": "generate_key", + "output_path": "key" + }, + { + "input": "{\"network_identifier\": {{network}}, \"public_key\": {{key.public_key}}}", + "type": "derive", + "output_path": "account" + }, + { + "input": "{\"account_identifier\": {{account.account_identifier}}, \"keypair\": {{key}}}", + "type": "save_account" + } + ] + } + ] + }, + { + "name": "transfer", + "concurrency": 1, + "scenarios": [ + { + "name": "transfer", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 1\", \"metadata\":{\"is_beacon\": false}}}", + "type": "set_variable", + "output_path": "transfer.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"53000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": {{sender.balance.value}}, \"right_value\": {{max_fee}}}", + "type": "math", + "output_path": "available_amount" + }, + { + "input": "{\"minimum\": \"1\", \"maximum\": {{available_amount}}}", + "type": "random_number", + "output_path": "recipient_amount" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": \"0\", \"right_value\":{{recipient_amount}}}", + "type": "math", + "output_path": "sender_amount" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "transfer.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"NativeTransfer\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":{{sender_amount}},\"currency\":{{currency}}}},{\"operation_identifier\":{\"index\":1},\"related_operations\":[{\"index\":0}],\"type\":\"NativeTransfer\",\"account\":{{recipient.account_identifier}},\"amount\":{\"value\":{{recipient_amount}},\"currency\":{{currency}}}}]", + "type": "set_variable", + "output_path": "transfer.operations" + } + ] + } + ] + }, + { + "name": "cross_shard_transfer", + "concurrency": 10, + "scenarios": [ + { + "name": "transfer", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 1\", \"metadata\":{\"is_beacon\": false}}}", + "type": "set_variable", + "output_path": "transfer.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"53000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": {{sender.balance.value}}, \"right_value\": {{max_fee}}}", + "type": "math", + "output_path": "available_amount" + }, + { + "input": "{\"minimum\": \"1\", \"maximum\": {{available_amount}}}", + "type": "random_number", + "output_path": "recipient_amount" + }, + { + "input": "{\"operation\":\"subtraction\", \"left_value\": \"0\", \"right_value\":{{recipient_amount}}}", + "type": "math", + "output_path": "sender_amount" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "transfer.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"NativeCrossShardTransfer\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":{{sender_amount}},\"currency\":{{currency}}}, \"metadata\":{\"from\":{{sender.account_identifier}}, \"to\": {{recipient.account_identifier}}}}]", + "type": "set_variable", + "output_path": "transfer.operations" + }, + { + "input": "{\"to_shard\":0, \"from_shard\":1}", + "type": "set_variable", + "output_path": "transfer.preprocess_metadata" + } + ] + } + ] + }, + { + "name": "contract_creation", + "concurrency": 10, + "scenarios": [ + { + "name": "transfer", + "actions": [ + { + "input": "{\"network\":\"Testnet\", \"blockchain\":\"Harmony\", \"sub_network_identifier\":{\"network\":\"shard 1\", \"metadata\":{\"is_beacon\": false}}}", + "type": "set_variable", + "output_path": "transfer.network" + }, + { + "input": "{\"symbol\":\"ONE\", \"decimals\":18}", + "type": "set_variable", + "output_path": "currency" + }, + { + "input": "{\"minimum_balance\":{\"value\": \"10000000000000000\", \"currency\": {{currency}}}}", + "type": "find_balance", + "output_path": "sender" + }, + { + "input": "\"530000000000000000\"", + "type": "set_variable", + "output_path": "max_fee" + }, + { + "input": "{\"not_account_identifier\":[{{sender.account_identifier}}], \"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\": 100, \"create_probability\": 50}", + "type": "find_balance", + "output_path": "recipient" + }, + { + "input": "\"1\"", + "type": "set_variable", + "output_path": "transfer.confirmation_depth" + }, + { + "input": "[{\"operation_identifier\":{\"index\":0},\"type\":\"ContractCreation\",\"account\":{{sender.account_identifier}},\"amount\":{\"value\":\"0\",\"currency\":{{currency}}}}]", + "type": "set_variable", + "output_path": "transfer.operations" + }, + { + "input": "{\"data\": \"0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061019c806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a723158209b80813a158b44af65aee232b44c0ac06472c48f4abbe298852a39f0ff34a9f264736f6c63430005100032\"}", + "type": "set_variable", + "output_path": "transfer.preprocess_metadata" + } + ] + } + ] + } + ], + "end_conditions": { + "create_account": 1, + "transfer": 1, + "cross_shard_transfer": 1, + "contract_creation": 1 + } + } +} diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000000..a6cbf08908 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,5 @@ +pyhmy==20.5.16 +pytest==6.2.5 +pytest-ordering==0.6 +pytest-xdist==1.33.0 +flaky==3.7.0 \ No newline at end of file diff --git a/tests/rpc_tests/conftest.py b/tests/rpc_tests/conftest.py new file mode 100644 index 0000000000..1ba1ad4c9c --- /dev/null +++ b/tests/rpc_tests/conftest.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Pytest config file. All functions here get ran before collecting all tests and executing them. +""" +import time + +from pyhmy import ( + util, +) +from pyhmy.rpc.request import ( + base_request +) + +from txs import ( + tx_timeout, + endpoints, + initial_funding, + get_transaction +) +from utils import ( + is_valid_json_rpc, +) + + +def pytest_sessionstart(session): + """ + Start the test session by sending initial test funds. + Will block until transactions are confirmed on-chain. + """ + assert util.is_active_shard(endpoints[0], delay_tolerance=20), "Shard 0 is not making progress..." + assert util.is_active_shard(endpoints[1], delay_tolerance=20), "Shard 1 is not making progress..." + + # Send all txs. Note that this is the only place to break the txs invariant. + for tx in initial_funding: + response = base_request('hmy_sendRawTransaction', params=[tx["signed-raw-tx"]], + endpoint=endpoints[tx["from-shard"]]) + assert is_valid_json_rpc(response), f"Invalid JSON response: {response}" + # Do not check for errors since resending initial txs is fine & failed txs will be caught in confirm timeout. + + # Confirm all txs within 2x timeout window (since all initial txs could be in 2 blocks). + start_time = time.time() + while time.time() - start_time <= 2 * tx_timeout: + sent_txs = [] + for tx in initial_funding: + tx_response = get_transaction(tx["hash"], tx["from-shard"]) + if (tx_response is not None): + sent_txs.append(tx_response['blockNumber'] is not None) + else: + sent_txs.append(tx_response is not None) + if all(sent_txs): + return + raise AssertionError("Could not confirm initial transactions on-chain.") \ No newline at end of file diff --git a/tests/rpc_tests/test_account.py b/tests/rpc_tests/test_account.py new file mode 100644 index 0000000000..382d6e7186 --- /dev/null +++ b/tests/rpc_tests/test_account.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Tests here are related to account information. Some tests require a +feedback loop with the chain. + +TODO: negative test cases + +As with all tests, there are 2 JSON-RPC versions/namespaces (v1 & v2) where their difference +is only suppose to be in the types of their params & returns. v1 keeps everything in hex and +v2 uses decimal when possible. However, there are some (legacy) discrepancies that some tests +enforce. These tests are noted and should NOT be broken. +""" +import pytest +from pyhmy.rpc.request import ( + base_request +) + +from txs import ( + endpoints, + initial_funding, + get_transaction, + send_and_confirm_transaction +) +from utils import ( + check_and_unpack_rpc_response, + assert_valid_json_structure +) + + +@pytest.fixture(scope="module") +def account_test_tx(): + """ + Fixture to send (if needed) and return a transaction to be + used for all tests in this test module. + """ + test_tx = { + "from": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "to": "one1s92wjv7xeh962d4sfc06q0qauxak4k8hh74ep3", + "amount": "1000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x3759ab736798efe609bd1eb69145616ccc57baea99a9abab4e259e935f488bc5", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac008252088080948154e933c6cdcba536b04e1fa03c1de1bb6ad8f7893635c9adc5dea000008028a086f785f5893efe3ff12b3fdaa0e52ae6a7b5b6897edb15f177836df355cbf2dea0648149e5feccfff1418e8cd6ac55bb9f26423f95344e558d917b25d4b7ac88df", + } + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == test_tx["from"] and tx["to-shard"] == test_tx["from-shard"]: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test transaction from address {test_tx['from']} " + f"not found in set of initially funded accounts.") + + tx_response = get_transaction(test_tx["hash"], test_tx["from-shard"]) + return send_and_confirm_transaction(test_tx) if tx_response is None else tx_response + + +def test_get_transactions_count(account_test_tx): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = 0 + + # Check v1, SENT + raw_response = base_request("hmy_getTransactionsCount", + params=[account_test_tx["to"], "SENT"], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 0, f"Expected account {account_test_tx['to']} to have 0 sent transactions" + + # Check v2, SENT + raw_response = base_request("hmyv2_getTransactionsCount", + params=[account_test_tx["to"], "SENT"], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 0, f"Expected account {account_test_tx['to']} to have 0 sent transactions" + + # Check v1, RECEIVED + raw_response = base_request("hmy_getTransactionsCount", + params=[account_test_tx["to"], "RECEIVED"], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {account_test_tx['to']} to have 1 received transactions" + + # Check v2, RECEIVED + raw_response = base_request("hmyv2_getTransactionsCount", + params=[account_test_tx["to"], "RECEIVED"], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {account_test_tx['to']} to have 1 received transactions" + + # Check v1, ALL + raw_response = base_request("hmy_getTransactionsCount", + params=[account_test_tx["to"], "ALL"], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {account_test_tx['to']} to have 1 received transactions" + + # Check v2, ALL + raw_response = base_request("hmyv2_getTransactionsCount", + params=[account_test_tx["to"], "ALL"], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {account_test_tx['to']} to have 1 received transactions" + + +def test_get_transactions_history_v1(): + reference_response_full = { + "transactions": [ + { + "blockHash": "0x28ddf57c43a3d91069d58be0e5cb8daac04261b97dd34d3c5c361f7bd941e657", + "blockNumber": "0xf", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": "0x5f0d84e2", + "gas": "0x5208", + "gasPrice": "0x6fc23ac00", + "hash": "0x3759ab736798efe609bd1eb69145616ccc57baea99a9abab4e259e935f488bc5", + "input": "0x", + "nonce": "0x0", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": "0x0", + "value": "0x152d02c7e14af6800000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + ] + } + + reference_response_short = { + "transactions": [ + "0x3759ab736798efe609bd1eb69145616ccc57baea99a9abab4e259e935f488bc5", + ] + } + + address = initial_funding[0]["from"] + + # Check short tx + raw_response = base_request("hmy_getTransactionsHistory", + params=[{ + "address": address, + "pageIndex": 0, + "pageSize": 1000, + "fullTx": False, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response_short, response) + + # Check long tx + raw_response = base_request("hmy_getTransactionsHistory", + params=[{ + "address": address, + "pageIndex": 0, + "pageSize": 1000, + "fullTx": True, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response_full, response) + + +def test_get_transactions_history_v2(): + reference_response_full = { + "transactions": [ + { + "blockHash": "0x28ddf57c43a3d91069d58be0e5cb8daac04261b97dd34d3c5c361f7bd941e657", + "blockNumber": 15, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": 1594721506, + "gas": 21000, + "gasPrice": 30000000000, + "hash": "0x3759ab736798efe609bd1eb69145616ccc57baea99a9abab4e259e935f488bc5", + "input": "0x", + "nonce": 0, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": 0, + "value": 100000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + ] + } + + reference_response_short = { + "transactions": [ + "0x3759ab736798efe609bd1eb69145616ccc57baea99a9abab4e259e935f488bc5", + ] + } + + address = initial_funding[0]["from"] + + # Check short tx + raw_response = base_request("hmyv2_getTransactionsHistory", + params=[{ + "address": address, + "pageIndex": 0, + "pageSize": 1000, + "fullTx": False, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response_short, response) + + # Check long tx + raw_response = base_request("hmyv2_getTransactionsHistory", + params=[{ + "address": address, + "pageIndex": 0, + "pageSize": 1000, + "fullTx": True, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response_full, response) + + +def test_get_balances_by_block_number_v1(account_test_tx): + reference_response = "0x3635c9adc5dea00000" + + raw_response = base_request("hmy_getBalanceByBlockNumber", + params=[account_test_tx["to"], account_test_tx["blockNumber"]], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == account_test_tx[ + "value"], f"Expected balance of {account_test_tx['to']} is {account_test_tx['value']}" + + +def test_get_balances_by_block_number_v2(account_test_tx): + reference_response = 1000000000000000000000 + + raw_response = base_request("hmyv2_getBalanceByBlockNumber", + params=[account_test_tx["to"], int(account_test_tx["blockNumber"], 16)], + endpoint=endpoints[account_test_tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + acc_tx_value = int(account_test_tx["value"], 16) + assert response == acc_tx_value, f"Expected balance of {account_test_tx['to']} is {acc_tx_value}" diff --git a/tests/rpc_tests/test_blockchain.py b/tests/rpc_tests/test_blockchain.py new file mode 100644 index 0000000000..b378c1a00a --- /dev/null +++ b/tests/rpc_tests/test_blockchain.py @@ -0,0 +1,783 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Tests here do not require transaction or a feedback loop with the chain +(other than the initial transactions) to validate functionality. + +TODO: negative test cases + +As with all tests, there are 2 JSON-RPC versions/namespaces (v1 & v2) where their difference +is only suppose to be in the types of their params & returns. v1 keeps everything in hex and +v2 uses decimal when possible. However, there are some (legacy) discrepancies that some tests +enforce. These tests are noted and should NOT be broken. +""" + +from pyhmy import ( + account, + transaction +) +from pyhmy.rpc.request import ( + base_request +) + +import txs +from flaky import flaky +from txs import ( + endpoints, + initial_funding +) +from utils import ( + assert_valid_json_structure, + check_and_unpack_rpc_response, + mutually_exclusive_test, + rerun_delay_filter +) + +_mutex_scope = "blockchain" + + +def test_invalid_method(): + reference_response = { + "code": -32601, + "message": "The method test_ does not exist/is not available" + } + + raw_response = base_request(f"invalid_{hash('method')}", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=True) + assert_valid_json_structure(reference_response, response) + assert response["code"] == reference_response["code"] + + +def test_net_peer_count_v1(): + """ + Note that this is NOT a `hmy` RPC, however, there are 2 versions of it. + """ + raw_response = base_request("net_peerCount", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + + +def test_net_peer_count_v2(): + """ + Note that this is NOT a `hmy` RPC, however, there are 2 versions of it. + """ + raw_response = base_request("netv2_peerCount", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) # Must be an integer in base 10 + + +def test_get_node_metadata(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "blskey": [ + "65f55eb3052f9e9f632b2923be594ba77c55543f5c58ee1454b9cfd658d25e06373b0f7d42a19c84768139ea294f6204" + ], + "version": "Harmony (C) 2020. harmony, version v6110-v2.1.9-34-g24ec31c1 (danielvdm@ 2020-07-11T05:03:50-0700)", + "network": "localnet", + "chain-config": { + "chain-id": 2, + "cross-tx-epoch": 0, + "cross-link-epoch": 2, + "staking-epoch": 2, + "prestaking-epoch": 0, + "quick-unlock-epoch": 0, + "eip155-epoch": 0, + "s3-epoch": 0, + "receipt-log-epoch": 0 + }, + "is-leader": True, + "shard-id": 0, + "current-epoch": 0, + "blocks-per-epoch": 5, + "role": "Validator", + "dns-zone": "", + "is-archival": False, + "node-unix-start-time": 1594469045, + "p2p-connectivity": { + "total-known-peers": 24, + "connected": 23, + "not-connected": 1 + } + } + + # Check v1 + raw_response = base_request("hmy_getNodeMetadata", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["shard-id"] == 0 + assert response["network"] == "localnet" + assert response["chain-config"]["chain-id"] == 2 + + # Check v2 + raw_response = base_request("hmyv2_getNodeMetadata", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["shard-id"] == 0 + assert response["network"] == "localnet" + assert response["chain-config"]["chain-id"] == 2 + + +def test_get_sharding_structure(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "current": True, + "http": "http://127.0.0.1:9500", + "shardID": 0, + "ws": "ws://127.0.0.1:9800" + } + + # Check v1 + raw_response = base_request("hmy_getShardingStructure", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, list), f"Expected response to be of type list, not {type(response)}" + for d in response: + assert isinstance(d, dict), f"Expected type dict in response elements, not {type(d)}" + assert_valid_json_structure(reference_response, d) + assert response[0]["current"] + + # Check v2 + raw_response = base_request("hmyv2_getShardingStructure", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, list), f"Expected response to be of type list, not {type(response)}" + for d in response: + assert isinstance(d, dict), f"Expected type dict in response elements, not {type(d)}" + assert_valid_json_structure(reference_response, d) + assert response[0]["current"] + + +@txs.staking +def test_get_latest_header(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "blockHash": "0x4e9faaf05bd7ed0ed392b3b5b19f2d2df993e60436c94b61b8afae6998b854b5", + "blockNumber": 83, + "shardID": 0, + "leader": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "viewID": 83, + "epoch": 15, + "timestamp": "2020-07-12 14:25:05 +0000 UTC", + "unixtime": 1594563905, + "lastCommitSig": "76e8365fdbd947f74d86f15072546f594f8aaf3f6bf0b085df1d81079b760e17da1666d8d07f5c744e200f81a5fa750901d0dc871a4dbe5461efa779553db3f95785d168701c774b23d2326f0d906e47d534a34c87f4ace5e4ed2242860bfc0e", + "lastCommitBitmap": "3f", + "crossLinks": [ + { + "hash": "0x9dda6ad7fdec1e0f76b87bbea432e12c8668dbb2de9100e87442adfb1c7d1f70", + "block-number": 80, + "view-id": 80, + "signature": "73f8e045c0cee4accfd259a78ea440ef2cf8c95d1c2e0e069725b35034c63e27f4db8ec5e1983d1c21831561967d0101ba556977e047a032e2c0f70bc3dc658ae245cb3392c837aed46119fa95ab39aad4ac926a206ab174304be15bb17df68a", + "signature-bitmap": "3f", + "shard-id": 1, + "epoch-number": 14 + } + ] + } + + # Check v1 + raw_response = base_request("hmy_latestHeader", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["shardID"] == 0 + + # Check v2 + raw_response = base_request("hmyv2_latestHeader", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["shardID"] == 0 + + +def test_get_latest_chain_headers(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "beacon-chain-header": { + "epoch": 18, + "extraData": "0x", + "gasLimit": "0x4c4b400", + "gasUsed": "0x0", + "hash": "0xdb6099006bb637578a94fa3003b2b68947ae8fcdc7e9f89ea0f83edd5ad65c9e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0", + "miner": "0x6911b75b2560be9a8f71164a33086be4511fc99a", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "number": "0xab", + "sha3Uncles": + '0x0000000000000000000000000000000000000000000000000000000000000000', + "nonce": '0x0000000000000000', + "parentHash": "0x9afbaa3db3c2f5393b7b765aa48091c7a6cc3c3fdf19fb88f8ee2c88e257988d", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "shardID": 0, + "stateRoot": "0x4d0b5b168bd3214e32f95718ef591e04c54f060f89e4304c8d4ff2745ebad3a9", + "timestamp": "0x60751990", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "viewID": 171 + }, + "shard-chain-header": { + "epoch": 17, + "extraData": "0x", + "gasLimit": "0x4c4b400", + "gasUsed": "0x0", + "hash": "0xdf4c2be8e676f728a419415bdd393a5c174e0b1431e016f870d0777d86668708", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0", + "miner": "0xd06193871db8d5bc92dead4780e3624038174e88", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "number": "0xa7", + "sha3Uncles": + '0x0000000000000000000000000000000000000000000000000000000000000000', + "nonce": '0x0000000000000000', + "parentHash": "0x336990a12d8697c5f9247790261aa1bdea33aed37031d09664680b86779f08a6", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "shardID": 1, + "stateRoot": "0xddd8a842df3ffd77555d64ab782abf6effe95bc2eab48610ac05a5445b55df92", + "timestamp": "0x60751991", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "viewID": 167 + } + } + + # Check v1 + raw_response = base_request( + "hmy_getLatestChainHeaders", endpoint=endpoints[1]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["beacon-chain-header"]["shardID"] == 0 + assert response["shard-chain-header"]["shardID"] == 1 + + # Check v2 + raw_response = base_request("hmyv2_getLatestChainHeaders", endpoint=endpoints[1]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["beacon-chain-header"]["shardID"] == 0 + assert response["shard-chain-header"]["shardID"] == 1 + + +def test_get_leader_address(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = "0x6911b75b2560be9a8f71164a33086be4511fc99a" + + # Check v1 + raw_response = base_request("hmy_getLeader", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert type(reference_response) == type(response) + if response.startswith("one1"): + assert account.is_valid_address(response), f"Leader address is not a valid ONE address" + else: + ref_len = len(reference_response.replace("0x", "")) + assert ref_len == len(response.replace("0x", "")), f"Leader address hash is not of length {ref_len}" + + # Check v2 + raw_response = base_request("hmyv2_getLeader", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + if response.startswith("one1"): + assert account.is_valid_address(response), f"Leader address is not a valid ONE address" + else: + ref_len = len(reference_response.replace("0x", "")) + assert ref_len == len(response.replace("0x", "")), f"Leader address hash is not of length {ref_len}" + + +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@txs.cross_shard +def test_get_block_signer_keys(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + "65f55eb3052f9e9f632b2923be594ba77c55543f5c58ee1454b9cfd658d25e06373b0f7d42a19c84768139ea294f6204", + ] + + # Check v1 + raw_response = base_request("hmy_getBlockSignerKeys", params=["0x2"], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + # Check v2 + raw_response = base_request("hmyv2_getBlockSignerKeys", params=[2], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +def test_get_header_by_number(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "blockHash": "0xb718a66ef2b7764fa75b40bfe7047d015197a65ae4a9c4f2007501825025564c", + "blockNumber": 1, + "shardID": 0, + "leader": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "viewID": 1, + "epoch": 0, + "timestamp": "2020-07-12 14:14:17 +0000 UTC", + "unixtime": 1594563257, + "lastCommitSig": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "lastCommitBitmap": "", + "crossLinks": [] + } + + # Check v1 + raw_response = base_request("hmy_getHeaderByNumber", params=["0x0"], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["shardID"] == 0 + + # Check v2 + raw_response = base_request("hmyv2_getHeaderByNumber", params=[0], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["shardID"] == 0 + + +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@txs.cross_shard +def test_get_block_signers(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + "one1gh043zc95e6mtutwy5a2zhvsxv7lnlklkj42ux" + ] + + # Check v1 + raw_response = base_request("hmy_getBlockSigners", params=["0x2"], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert len(response) > 0, "expect at least 1 signer" + + # Check v2 + raw_response = base_request("hmyv2_getBlockSigners", params=[2], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert len(response) > 0, "expect at least 1 signer" + + +def test_get_block_number_v1(): + raw_response = base_request("hmy_blockNumber", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + + +def test_get_block_number_v2(): + raw_response = base_request("hmyv2_blockNumber", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) # Must be an integer in base 10 + + +def test_get_epoch_v1(): + raw_response = base_request("hmy_getEpoch", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + + +def test_get_epoch_v2(): + raw_response = base_request("hmyv2_getEpoch", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) # Must be an integer + + +def test_get_gas_price_v1(): + raw_response = base_request("hmy_gasPrice", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + + +def test_get_gas_price_v2(): + raw_response = base_request("hmyv2_gasPrice", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) # Must be an integer in base 10 + + +def test_get_protocol_version_v1(): + raw_response = base_request("hmy_protocolVersion", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + + +def test_get_protocol_version_v2(): + raw_response = base_request("hmyv2_protocolVersion", endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) # Must be an integer in base 10 + + +def test_get_block_transaction_count_by_number_v1(): + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + + raw_response = base_request("hmy_getBlockTransactionCountByNumber", params=[init_tx["blockNumber"]], + endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + assert int(response, 16) > 0, "Expected transaction count > 0 due to initial transactions" + + +def test_get_block_transaction_count_by_number_v2(): + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + + raw_response = base_request("hmyv2_getBlockTransactionCountByNumber", params=[int(init_tx["blockNumber"], 16)], + endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) + assert response > 0, "Expected transaction count > 0 due to initial transactions" + + +def test_get_block_transaction_count_by_hash_v1(): + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + + raw_response = base_request("hmy_getBlockTransactionCountByHash", params=[init_tx["blockHash"]], + endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + assert int(response, 16) > 0, "Expected transaction count > 0 due to initial transactions" + + +def test_get_block_transaction_count_by_hash_v2(): + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + + raw_response = base_request("hmyv2_getBlockTransactionCountByHash", params=[init_tx["blockHash"]], + endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, int) + assert response > 0, "Expected transaction count > 0 due to initial transactions" + + +def test_get_block_by_number_v1(): + reference_response = { + "difficulty": 0, + "epoch": "0x0", + "extraData": "0x", + "gasLimit": "0x4c4b400", + "gasUsed": "0x0", + "hash": "0x0994da932016ba93937ad46b9a1207ecd6d4fbd689d7f8ddf1f926cd3ebc6016", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqquzw7vz", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": "0x1", + "parentHash": "0x61610810993c42bacd55a124e3b9009b9ae225a2f727750db4d2171504be59fb", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "size": "0x31e", + "stakingTransactions": [], + "stateRoot": "0x9e470e803db498e6ba3c9108d3f951060e7121289c2354b8b185349ddef4fc0a", + "timestamp": "0x5f09ad95", + "transactions": [], + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [], + "viewID": "0x1" + } + + raw_response = base_request("hmy_getBlockByNumber", params=["0x0", True], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +def test_get_block_by_number_v2(): + """ + Note the use of a JSON object in the param. This is different from v1. + """ + reference_response = { + "difficulty": 0, + "epoch": 0, + "extraData": "0x", + "gasLimit": 80000000, + "gasUsed": 0, + "hash": "0x0994da932016ba93937ad46b9a1207ecd6d4fbd689d7f8ddf1f926cd3ebc6016", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqquzw7vz", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": 1, + "parentHash": "0x61610810993c42bacd55a124e3b9009b9ae225a2f727750db4d2171504be59fb", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "size": 798, + "stakingTransactions": [], + "stateRoot": "0x9e470e803db498e6ba3c9108d3f951060e7121289c2354b8b185349ddef4fc0a", + "timestamp": 1594469781, + "transactions": [], + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [], + "viewID": 1 + } + + raw_response = base_request("hmyv2_getBlockByNumber", params=[0, {"InclStaking": True}], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +@mutually_exclusive_test(scope=_mutex_scope) +def test_get_blocks_v1(): + """ + Note: param options for 'withSigners' will NOT return any sensical data + in staking epoch (since it returns ONE addresses) and is subject to removal, thus is not tested here. + """ + reference_response_blk = { + "difficulty": 0, + "epoch": "0x0", + "extraData": "0x", + "gasLimit": "0x4c4b400", + "gasUsed": "0x19a28", + "hash": "0xf14c18213b1845ee09c41c5ecd321be5b745ef42e80d8e8a6bfd116452781465", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqquzw7vz", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": "0x3", + "parentHash": "0xe4fe8484b94d3498acc183a8bcf9e0bef6d30b1a81d5628fbc67f9a7328651e8", + "receiptsRoot": "0x100f3336862d22706bbe26d67e5abf90f8f25ec5a22c4446835b6beaa6b59536", + "size": "0x4d7", + "stakingTransactions": [], + "stateRoot": "0x1dc641cf516efe9ff2250f9c8db069ba4b9954160bf70cbe376ed11904b4edf5", + "timestamp": "0x5f0c8592", + "transactions": [ + { + "blockHash": "0xf14c18213b1845ee09c41c5ecd321be5b745ef42e80d8e8a6bfd116452781465", + "blockNumber": "0x3", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": "0x5f0c8592", + "gas": "0x5208", + "gasPrice": "0x3b9aca00", + "hash": "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", + "input": "0x", + "nonce": "0x0", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": "0x0", + "value": "0x152d02c7e14af6800000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + }, + ], + "transactionsRoot": "0x8954e7b3ec6ef4b04dcaf2829d9ce8ed764f636445fe77d2f4e5ef157e69dbbd", + "uncles": [], + "viewID": "0x3" + } + + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + start_blk, end_blk = hex(max(0, int(init_tx["blockNumber"], 16) - 2)), init_tx["blockNumber"] + raw_response = base_request("hmy_getBlocks", + params=[start_blk, end_blk, { + "fullTx": True, + "inclStaking": True + }], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + for blk in response: + assert_valid_json_structure(reference_response_blk, blk) + assert len(response[-1]["transactions"]) > 0, "Expected transaction on last block due to initial transactions" + start_num, end_num = int(start_blk, 16), int(end_blk, 16) + for blk in response: + blk_num = int(blk["number"], 16) + assert start_num <= blk_num <= end_num, f"Got block number {blk_num}, which is not in range [{start_num},{end_num}]" + + +@mutually_exclusive_test(scope=_mutex_scope) +def test_get_blocks_v2(): + """ + Only difference in param of RPC is hex string in v1 and decimal in v2. + + Note: param options for 'withSigners' will NOT return any sensical data + in staking epoch (since it returns ONE addresses) and is subject to removal, thus is not tested here. + """ + reference_response_blk = { + "difficulty": 0, + "epoch": 0, + "extraData": "0x", + "gasLimit": 80000000, + "gasUsed": 105000, + "hash": "0xf14c18213b1845ee09c41c5ecd321be5b745ef42e80d8e8a6bfd116452781465", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqquzw7vz", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": 3, + "parentHash": "0xe4fe8484b94d3498acc183a8bcf9e0bef6d30b1a81d5628fbc67f9a7328651e8", + "receiptsRoot": "0x100f3336862d22706bbe26d67e5abf90f8f25ec5a22c4446835b6beaa6b59536", + "size": 1239, + "stakingTransactions": [], + "stateRoot": "0x1dc641cf516efe9ff2250f9c8db069ba4b9954160bf70cbe376ed11904b4edf5", + "timestamp": 1594656146, + "transactions": [ + { + "blockHash": "0xf14c18213b1845ee09c41c5ecd321be5b745ef42e80d8e8a6bfd116452781465", + "blockNumber": 3, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": 1594656146, + "gas": 21000, + "gasPrice": 1000000000, + "hash": "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", + "input": "0x", + "nonce": 0, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": 0, + "value": 100000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + }, + ], + "transactionsRoot": "0x8954e7b3ec6ef4b04dcaf2829d9ce8ed764f636445fe77d2f4e5ef157e69dbbd", + "uncles": [], + "viewID": 3 + } + + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + start_blk, end_blk = max(0, int(init_tx["blockNumber"], 16) - 2), int(init_tx["blockNumber"], 16) + raw_response = base_request("hmyv2_getBlocks", + params=[start_blk, end_blk, { + "fullTx": True, + "inclStaking": True + }], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + for blk in response: + assert_valid_json_structure(reference_response_blk, blk) + assert len(response[-1]["transactions"]) > 0, "Expected transaction on last block due to initial transactions" + for blk in response: + assert start_blk <= blk[ + "number"] <= end_blk, f"Got block number {blk['number']}, which is not in range [{start_blk},{end_blk}]" + + +@mutually_exclusive_test(scope=_mutex_scope) +def test_get_block_by_hash_v1(): + reference_response = { + "difficulty": 0, + "epoch": "0x0", + "extraData": "0x", + "gasLimit": "0x4c4b400", + "gasUsed": "0x19a28", + "hash": "0x8e0ca00640ea70afe078d02fd571085f14d5953dca7be8ef4efc6a02db090156", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqquzw7vz", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": "0x9", + "parentHash": "0xd5d0e786f1a0c6d8d2ea038ef5f8272bb4e4def1838d61b7e1c395f4b763c09d", + "receiptsRoot": "0x100f3336862d22706bbe26d67e5abf90f8f25ec5a22c4446835b6beaa6b59536", + "size": "0x96a", + "stakingTransactions": [], + "stateRoot": "0x8a39cac10f8d917564a4e6033dc303d6a47d9fc8768c220640de5bb89765e0cf", + "timestamp": "0x5f0c976e", + "transactions": [ + { + "blockHash": "0x8e0ca00640ea70afe078d02fd571085f14d5953dca7be8ef4efc6a02db090156", + "blockNumber": "0x9", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": "0x5f0c976e", + "gas": "0x5208", + "gasPrice": "0x3b9aca00", + "hash": "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", + "input": "0x", + "nonce": "0x0", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": "0x0", + "value": "0x152d02c7e14af6800000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + }, + ], + "transactionsRoot": "0x8954e7b3ec6ef4b04dcaf2829d9ce8ed764f636445fe77d2f4e5ef157e69dbbd", + "uncles": [], + "viewID": "0x9" + } + + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + raw_response = base_request("hmy_getBlockByHash", + params=[init_tx["blockHash"], True], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert len(response["transactions"]) > 0, "Expected transaction on block due to initial transactions" + for tx in response["transactions"]: + assert tx["blockHash"] == init_tx[ + "blockHash"], f"Transaction in block {init_tx['blockHash']} does not have same block hash" + assert tx["shardID"] == init_tx_record[ + "from-shard"], f"Transaction in block from shard {init_tx_record['from-shard']} does not have same from shard ({tx['shardID']})" + + +@mutually_exclusive_test(scope=_mutex_scope) +def test_get_block_by_hash_v2(): + """ + Note the use of a JSON object in the param. This is different from v1. + + Note: param options for 'withSigners' will NOT return any sensical data + in staking epoch (since it returns ONE addresses) and is subject to removal, thus is not tested here. + """ + reference_response = { + "difficulty": 0, + "epoch": 0, + "extraData": "0x", + "gasLimit": 80000000, + "gasUsed": 105000, + "hash": "0x8e0ca00640ea70afe078d02fd571085f14d5953dca7be8ef4efc6a02db090156", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqquzw7vz", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": 9, + "parentHash": "0xd5d0e786f1a0c6d8d2ea038ef5f8272bb4e4def1838d61b7e1c395f4b763c09d", + "receiptsRoot": "0x100f3336862d22706bbe26d67e5abf90f8f25ec5a22c4446835b6beaa6b59536", + "size": 2410, + "stateRoot": "0x8a39cac10f8d917564a4e6033dc303d6a47d9fc8768c220640de5bb89765e0cf", + "timestamp": 1594660718, + "transactions": [ + { + "blockHash": "0x8e0ca00640ea70afe078d02fd571085f14d5953dca7be8ef4efc6a02db090156", + "blockNumber": 9, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": 1594660718, + "gas": 21000, + "gasPrice": 1000000000, + "hash": "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", + "input": "0x", + "nonce": 0, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": 0, + "value": 100000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + }, + ], + "transactionsRoot": "0x8954e7b3ec6ef4b04dcaf2829d9ce8ed764f636445fe77d2f4e5ef157e69dbbd", + "uncles": [], + "viewID": 9 + } + + init_tx_record = initial_funding[0] + init_tx = transaction.get_transaction_by_hash(init_tx_record["hash"], endpoints[init_tx_record["from-shard"]]) + raw_response = base_request("hmyv2_getBlockByHash", + params=[init_tx["blockHash"], { + "fullTx": True, + "inclTx": True + }], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert len(response["transactions"]) > 0, "Expected transaction on block due to initial transactions" + for tx in response["transactions"]: + assert tx["blockHash"] == init_tx[ + "blockHash"], f"Transaction in block {init_tx['blockHash']} does not have same block hash" + assert tx["shardID"] == init_tx_record[ + "from-shard"], f"Transaction in block from shard {init_tx_record['from-shard']} does not have same from shard ({tx['shardID']})" diff --git a/tests/rpc_tests/test_contract.py b/tests/rpc_tests/test_contract.py new file mode 100644 index 0000000000..d0a0347e60 --- /dev/null +++ b/tests/rpc_tests/test_contract.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Tests here are related to smart contracts & require a feedback loop with the chain. + +TODO: negative test cases + +As with all tests, there are 2 JSON-RPC versions/namespaces (v1 & v2) where their difference +is only suppose to be in the types of their params & returns. v1 keeps everything in hex and +v2 uses decimal when possible. However, there are some (legacy) discrepancies that some tests +enforce. These tests are noted and should NOT be broken. +""" +import traceback + +import pytest +from pyhmy import ( + transaction, + blockchain +) +from pyhmy.rpc.request import ( + base_request +) + +from txs import ( + initial_funding, + endpoints, + send_and_confirm_transaction, + get_transaction +) +from utils import ( + check_and_unpack_rpc_response, + is_valid_json_rpc +) + + +def _get_contract_address(tx_hash, shard): + """ + Helper function to get contract address from the tx_hash. + """ + assert isinstance(tx_hash, str), f"Sanity check: expected tx_hash to be of type str not {type(tx_hash)}" + assert isinstance(shard, int), f"Sanity check: expected shard to be of type int not {type(shard)}" + address = transaction.get_transaction_receipt(tx_hash, endpoints[shard])["contractAddress"] + assert address, f"Transaction {tx_hash} is not a deployment of a smart contract, got not contract address" + return address + + +@pytest.fixture(scope="module") +def deployed_contract(): + """ + Fixture to deploy a smart contract. + + Returns the transaction information (`contract_tx`) to be used by tests in this module. + + Note that this contract is the Migrations contract used by truffle. + """ + contract_tx = { + "from": "one156wkx832t0nxnaq6hxawy4c3udmnpzzddds60a", + "to": None, + "amount": None, + "from-shard": 0, + "to-shard": 0, + "hash": "0x7b818e63630dd41c7778e0a72ebd7e1f37ac9b92e5ee8050e46a252fa2a85757", + "nonce": "0x8", + "signed-raw-tx": "0xf90251808506fc23ac008366916c80808080b901fc608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061019c806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a723158209b80813a158b44af65aee232b44c0ac06472c48f4abbe298852a39f0ff34a9f264736f6c6343000510003228a016d5ca07b8fd32ac9ee0b9ce688ab0a384fc5dc8015b0629f3f9be728bdfbbdda03ffe944dd66c4af37262c15a2bc26d4e92602c3ca6546672e08060da8abf3a26", + "code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a723158209b80813a158b44af65aee232b44c0ac06472c48f4abbe298852a39f0ff34a9f264736f6c63430005100032" + } + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == contract_tx["from"] and tx["to-shard"] == contract_tx["from-shard"]: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test transaction from address {contract_tx['from']} " + f"not found in set of initially funded accounts.") + + if get_transaction(contract_tx["hash"], contract_tx["from-shard"]) is None: + tx = send_and_confirm_transaction(contract_tx) + assert tx["hash"] == contract_tx["hash"], f"Expected contract transaction hash to be {contract_tx['hash']}, " \ + f"got {tx['hash']}" + return contract_tx + + +def test_call_v1(deployed_contract): + """ + TODO: Real smart contract call, currently, it is an error case test. + """ + address = _get_contract_address(deployed_contract["hash"], deployed_contract["from-shard"]) + raw_response = base_request("hmy_call", params=[{"to": address}, "latest"], + endpoint=endpoints[deployed_contract["from-shard"]]) + assert is_valid_json_rpc(raw_response), f"Invalid JSON response: {raw_response}" + try: + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + except Exception as e: + pytest.skip("RPC format being reworked, fix when finished") + + +def test_call_v2(deployed_contract): + """ + TODO: Real smart contract call, currently, it is an error case test. + """ + address = _get_contract_address(deployed_contract["hash"], deployed_contract["from-shard"]) + block_number = blockchain.get_block_number(endpoint=endpoints[deployed_contract["from-shard"]]) + raw_response = base_request("hmyv2_call", params=[{"to": address}, block_number], + endpoint=endpoints[deployed_contract["from-shard"]]) + assert is_valid_json_rpc(raw_response), f"Invalid JSON response: {raw_response}" + try: + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + except Exception as e: + pytest.skip("RPC format being reworked, fix when finished") + + +def test_estimate_gas_v1(deployed_contract): + """ + RPC currently returns a constant, subject to change in the future, so skip for any error. + """ + try: + raw_response = base_request("hmy_estimateGas", params=[{}], endpoint=endpoints[deployed_contract["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert response == "0xcf08", f"Expected constant reply for estimate gas to be 0xcf08, got {response}" + except Exception as e: + pytest.skip(traceback.format_exc()) + pytest.skip(f"Exception: {e}") + + +def test_estimate_gas_v2(deployed_contract): + """ + RPC currently returns a constant, subject to change in the future, so skip for any error. + """ + try: + raw_response = base_request("hmyv2_estimateGas", params=[{}], + endpoint=endpoints[deployed_contract["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert response == "0xcf08", f"Expected constant reply for estimate gas to be 0xcf08, got {response}" + except Exception as e: + pytest.skip(traceback.format_exc()) + pytest.skip(f"Exception: {e}") + + +def test_get_code_v1(deployed_contract): + address = _get_contract_address(deployed_contract["hash"], deployed_contract["from-shard"]) + raw_response = base_request("hmy_getCode", params=[address, "latest"], + endpoint=endpoints[deployed_contract["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert response == deployed_contract["code"], f"Expected {deployed_contract['code']}, got {response}" + + +def test_get_code_v2(deployed_contract): + address = _get_contract_address(deployed_contract["hash"], deployed_contract["from-shard"]) + block_number = blockchain.get_block_number(endpoint=endpoints[deployed_contract["from-shard"]]) + raw_response = base_request("hmyv2_getCode", params=[address, block_number], + endpoint=endpoints[deployed_contract["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert response == deployed_contract["code"], f"Expected {deployed_contract['code']}, got {response}" + + +def test_get_storage_at_v1(deployed_contract): + address = _get_contract_address(deployed_contract["hash"], deployed_contract["from-shard"]) + raw_response = base_request("hmy_getStorageAt", params=[address, "0x0", "latest"], + endpoint=endpoints[deployed_contract["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string + + +def test_get_storage_at_v2(deployed_contract): + address = _get_contract_address(deployed_contract["hash"], deployed_contract["from-shard"]) + block_number = blockchain.get_block_number(endpoint=endpoints[deployed_contract["from-shard"]]) + raw_response = base_request("hmyv2_getStorageAt", params=[address, "0x0", block_number], + endpoint=endpoints[deployed_contract["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert isinstance(response, str) and response.startswith("0x") # Must be a hex string diff --git a/tests/rpc_tests/test_staking.py b/tests/rpc_tests/test_staking.py new file mode 100644 index 0000000000..14893760b7 --- /dev/null +++ b/tests/rpc_tests/test_staking.py @@ -0,0 +1,1796 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Tests here are related to staking functions & require a feedback loop with the chain. + +TODO: negative test cases + +As with all tests, there are 2 JSON-RPC versions/namespaces (v1 & v2) where their difference +is only suppose to be in the types of their params & returns. v1 keeps everything in hex and +v2 uses decimal when possible. However, there are some (legacy) discrepancies that some tests +enforce. These tests are noted and should NOT be broken. +""" +import json +import time +import random +import traceback + +import pytest +from flaky import flaky +from pyhmy import ( + blockchain, + staking +) +from pyhmy.rpc.request import ( + base_request +) + +import txs +from txs import ( + tx_timeout, + beacon_shard_id, + initial_funding, + endpoints, + send_and_confirm_staking_transaction, + send_staking_transaction, + get_staking_transaction +) +from utils import ( + check_and_unpack_rpc_response, + assert_valid_json_structure, + mutually_exclusive_test, + rerun_delay_filter, + assert_no_null_in_list +) + +_mutex_scope = "staking" + + +def _assert_validator_info(validator_data, validator_info): + """ + Helper function to check `validator_info` with the given `validator_data`. + + Validator data is expected to follow `stx` in s0_validator & s1_validator + """ + val = validator_info["validator"] + for attr in ["name", "identity", "website", "security-contact", "details"]: + assert validator_data[attr] == val[attr], f"Expected {validator_data[attr]}, got {val[attr]}" + for attr in ["rate", "max-rate", "max-change-rate"]: + assert validator_data[attr] == float(val[attr]), f"Expected {validator_data[attr]}, got {val[attr]}" + for attr in ["min-self-delegation", "max-total-delegation"]: + assert validator_data[attr] * 1e18 == float(val[attr]), f"Expected {validator_data[attr]}, got {val[attr]}" + assert validator_data["pub-bls-key"] in val[ + "bls-public-keys"], f"Expected pub-bls-key {validator_data['pub-bls-key']} " \ + f"in {val['bls-public-keys']}" + + +@pytest.fixture(scope="module") +@txs.staking +def s0_validator(): + """ + Fixture for the shard 0 validator (with a running external node). + + Returns the validator's create validator transaction (`stx`) + """ + stx = { + "validator-addr": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegator-addr": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "name": "test", + "identity": "test0", + "website": "test", + "security-contact": "test", + "details": "test", + "rate": 0.1, + "max-rate": 0.9, + "max-change-rate": 0.05, + "min-self-delegation": 10000, + "max-total-delegation": 10000000, + "amount": 10000, + "pub-bls-key": "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c", + "hash": "0xb1bffd62607b111afe507fb84c1cf498d39fbb201eea3064d4027375faef5c25", + "nonce": "0x0", + "signed-raw-tx": "0xf9015880f90106947946f5ce1eeb290965deef936cd9154c22173efeda8474657374857465737430847465737484746573748474657374ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500008a021e19e0c9bab24000008b084595161401484a000000f1b04f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270cf862b8606e1204740c90329827178361b635109e515a2334d970f44f29f3a98ff10bb351d8dd7fa03ceadcbe3e53be7b1bd0940c1e1fc58d2725e4bacf06831974edaf3291dfd5a0aa1e81c8a078e7e5e6cb9e58c750d6005afdd7b1548823804039a2118a021e19e0c9bab2400000808506fc23ac008350eefc28a0d19c875dffdfe925c8d57565f4fc46a310a251788b9964f989261e2ced71b539a06a60122a3860779bc754682e32df2529ef9af2ff5570ae3255e4a3cb8f2ff9d2" + } + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == stx["validator-addr"] and tx["to-shard"] == beacon_shard_id: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test staking transaction from address {stx['validator-addr']} " + f"not found in set of initially funded accounts (or not founded on s{beacon_shard_id})") + + if get_staking_transaction(stx["hash"]) is None: + tx = send_and_confirm_staking_transaction(stx) + assert tx["hash"] == stx["hash"], f"Expected create validator transaction hash to be {stx['hash']}, " \ + f"got {tx['hash']}" + assert get_staking_transaction(stx["hash"]) is not None, f"Transaction (hash {stx['hash']}) not found on chain." + + return stx + + +@pytest.fixture(scope="module") +@txs.staking +def s1_validator(): + """ + Fixture for the shard 1 validator (with a running external node). + + Returns the validator's create validator transaction (`stx`) + """ + stx = { + "validator-addr": "one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts", + "delegator-addr": "one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts", + "name": "test", + "identity": "test1", + "website": "test", + "security-contact": "test", + "details": "test", + "rate": 0.1, + "max-rate": 0.9, + "max-change-rate": 0.05, + "min-self-delegation": 10000, + "max-total-delegation": 10000000, + "amount": 10000, + #"pub-bls-key": "5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98", + "pub-bls-key": "5e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98", + "hash": "0xd0dd7ef72bbb1ba79b1f91d2f209513cf76b42f2466789352e9cadeed82a154f", + "nonce": "0x0", + "signed-raw-tx": "0xf9015880f90106949ec87071cf2aaa9842a32db7aabc3f6881944ad5da8474657374857465737431847465737484746573748474657374ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500008a021e19e0c9bab24000008b084595161401484a000000f1b05e2f14abeadf0e759beb1286ed6095d9d1b2d64ad394316991161c6f95237710e0a4beda8adeaefde4844ab4c4b2bf98f862b860e8bc184c4d5779ab7ab9fb8902b157b1257b1c4fa7e39649b2d900f0415f3aec0701f89e6840d42854559620627e871862b7b5075fad456fb43bc9eb5811c5b305d1d82838332623b109fbc033fd144387bb402e3bd1626a640b58d0b3ae66098a021e19e0c9bab2400000808506fc23ac008350ef0828a057e236df9dfc3159b1555f21107de424b60adc684b7ded1f35ba29bcce348e4aa04b47a7f2edc43abec69dd5881841cf8d9caaf14e0d54a4823575169008efba75" + } + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == stx["validator-addr"] and tx["to-shard"] == beacon_shard_id: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test staking transaction from address {stx['validator-addr']} " + f"not found in set of initially funded accounts (or not founded on s{beacon_shard_id})") + + if get_staking_transaction(stx["hash"]) is None: + tx = send_and_confirm_staking_transaction(stx) + assert tx["hash"] == stx["hash"], f"Expected create validator transaction hash to be {stx['hash']}, " \ + f"got {tx['hash']}" + assert get_staking_transaction(stx["hash"]) is not None, f"Transaction (hash {stx['hash']}) not found on chain." + + return stx + + +@txs.staking +@mutually_exclusive_test(scope=_mutex_scope) +@pytest.mark.run(after="test_get_validator_information") +def test_delegation(s1_validator): + """ + Note that this is not an explicit RPC test. It just tests that delegation works. + """ + stx = { + "validator-addr": "one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts", + "delegator-addr": "one1v895jcvudcktswcmg2sldvmxvtvvdj2wuxj3hx", + # web topple now acid repeat inspire tomato inside nominee reflect latin salmon garbage negative liberty win royal faith hammer lawsuit west toddler payment coffee + "amount": 10000, + "hash": "0x8384d8fc133fdb18bfdfda7b16e8bb1eb6105d9bd7f6ddfc1bb255e3edabae3c", + "nonce": "0x0", + "signed-raw-tx": "0xf88502f59461cb49619c6e2cb83b1b42a1f6b36662d8c6c94e949ec87071cf2aaa9842a32db7aabc3f6881944ad58a021e19e0c9bab2400000808506fc23ac00835121c427a03740ff6392841c59735b1ed68375da7b5289ff3c4fa78a72e4fc6abaa0b4eb6ca03f63e66bc7aacc19df97c68581e66396d134288f938561531d092204e2422ca9" + } + + assert stx["validator-addr"] == s1_validator["validator-addr"], f"Sanity check: Expected validator address " \ + f"to be {s1_validator['validator-addr']}" + + submitted_tx = False + if get_staking_transaction(stx["hash"]) is None: + tx = send_and_confirm_staking_transaction(stx) + submitted_tx = True + assert tx["hash"] == stx["hash"], f"Expected contract transaction hash to be {stx['hash']}, " \ + f"got {tx['hash']}" + assert get_staking_transaction(stx["hash"]) is not None, f"Transaction (hash {stx['hash']}) not found on chain." + + validator_info = staking.get_validator_information(stx["validator-addr"], endpoint=endpoints[beacon_shard_id]) + for delegation in validator_info["validator"]["delegations"]: + if delegation["delegator-address"] == stx["delegator-addr"]: + if submitted_tx: + assert delegation["amount"] == stx[ + "amount"] * 1e18, f"Expected delegated amount to be {stx['amount']} ONE" + return + + raise AssertionError(f"New delegation from {stx['delegator-addr']} not found on validator {stx['validator-addr']}") + + +@txs.staking +@mutually_exclusive_test(scope=_mutex_scope) +@pytest.mark.run(after="test_delegation") +@flaky(max_runs=6) +def test_undelegation(s1_validator): + """ + Note that this is not an explicit RPC test. It just tests that undelegation works. + """ + stx = { + "validator-addr": "one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts", + "delegator-addr": "one1v895jcvudcktswcmg2sldvmxvtvvdj2wuxj3hx", + # web topple now acid repeat inspire tomato inside nominee reflect latin salmon garbage negative liberty win royal faith hammer lawsuit west toddler payment coffee + "amount": 10000, + "hash": "0x75eb9a347ddf18ea1fb28fbc0c79c20ad8cae6a8702af16d517ff93b79254151", + "nonce": "0x1", + "signed-raw-tx": "0xf88503f59461cb49619c6e2cb83b1b42a1f6b36662d8c6c94e949ec87071cf2aaa9842a32db7aabc3f6881944ad58a021e19e0c9bab2400000018506fc23ac00835121c427a007e67bb2e26c5981c9fe065a37727d02d69d5c5013086c5ec166205bf3912555a05376e9cef058146ac81328f435c0a5921e068ae60be085ab062d78acf145a59d" + } + + assert stx["validator-addr"] == s1_validator["validator-addr"], f"Sanity check: Expected validator address " \ + f"to be {s1_validator['validator-addr']}" + + submitted_tx = False + if get_staking_transaction(stx["hash"]) is None: + tx = send_and_confirm_staking_transaction(stx) + submitted_tx = True + assert tx["hash"] == stx["hash"], f"Expected contract transaction hash to be {stx['hash']}, " \ + f"got {tx['hash']}" + assert get_staking_transaction(stx["hash"]) is not None, f"Transaction (hash {stx['hash']}) not found on chain." + + validator_info = staking.get_validator_information(stx["validator-addr"], endpoint=endpoints[beacon_shard_id]) + for delegation in validator_info["validator"]["delegations"]: + if delegation["delegator-address"] == stx["delegator-addr"]: + if submitted_tx: + assert len( + delegation["undelegations"]) > 0, f"Expected undelegations on validator {stx['validator-addr']}" + return + + raise AssertionError(f"New delegation from {stx['delegator-addr']} not found on validator {stx['validator-addr']}") + + +@txs.staking +@pytest.mark.run('first') +def test_get_all_validator_addresses(s0_validator, s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + 'one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e', + 'one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts' + ] + + # Check v1 + raw_response = base_request("hmy_getAllValidatorAddresses", params=[], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert s0_validator["validator-addr"] in response, f"Expected validator {s0_validator['validator-addr']} " \ + f"in validator list {response}" + assert s1_validator["validator-addr"] in response, f"Expected validator {s1_validator['validator-addr']} " \ + f"in validator list {response}" + + # Check v2 + raw_response = base_request("hmyv2_getAllValidatorAddresses", params=[], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert s0_validator["validator-addr"] in response, f"Expected validator {s0_validator['validator-addr']} " \ + f"in validator list {response}" + assert s1_validator["validator-addr"] in response, f"Expected validator {s1_validator['validator-addr']} " \ + f"in validator list {response}" + + +@txs.staking +def test_get_transaction_receipt_v1(s0_validator): + reference_response = { + "blockHash": "0x5890ceb902713f4f32f80764359e5b2ffec1fd84ad6f0bf75d5c22a6f1530d1d", + "blockNumber": "0x7", + "contractAddress": None, + "cumulativeGasUsed": "0x5121c4", + "gasUsed": "0x5121c4", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sender": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "status": "0x1", + "transactionHash": "0xf80460f1ad041a0a0e841da717fc5b7959b1a7e9a0ce9a25cd70c0ce40d5ff26", + "transactionIndex": "0x0", + "type": "0x0" + } + + raw_response = base_request("hmy_getTransactionReceipt", + params=[s0_validator["hash"]], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["transactionHash"] == s0_validator["hash"], f"Expected transaction {s0_validator['hash']}, " \ + f"got {response['transactionHash']}" + + +@txs.staking +def test_get_transaction_receipt_v2(s0_validator): + reference_response = { + "blockHash": "0x5890ceb902713f4f32f80764359e5b2ffec1fd84ad6f0bf75d5c22a6f1530d1d", + "blockNumber": 7, + "contractAddress": None, + "cumulativeGasUsed": 5317060, + "gasUsed": 5317060, + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sender": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "status": 1, + "transactionHash": "0xf80460f1ad041a0a0e841da717fc5b7959b1a7e9a0ce9a25cd70c0ce40d5ff26", + "transactionIndex": 0, + "type": 0 + } + + raw_response = base_request("hmyv2_getTransactionReceipt", + params=[s0_validator["hash"]], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["transactionHash"] == s0_validator["hash"], f"Expected transaction {s0_validator['hash']}, " \ + f"got {response['transactionHash']}" + + +@txs.staking +def test_get_staking_transactions_count(s0_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = 0 + + # Check v1, SENT + raw_response = base_request("hmy_getStakingTransactionsCount", + params=[s0_validator["validator-addr"], "SENT"], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {s0_validator['validator-addr']} to have 1 sent transactions" + + # Check v1, SENT + raw_response = base_request("hmyv2_getStakingTransactionsCount", + params=[s0_validator["validator-addr"], "SENT"], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {s0_validator['validator-addr']} to have 1 sent transactions" + + # Check v1, RECEIVED + raw_response = base_request("hmy_getStakingTransactionsCount", + params=[s0_validator["validator-addr"], "RECEIVED"], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 0, f"Expected account {s0_validator['validator-addr']} to have 0 received transactions" + + # Check v1, RECEIVED + raw_response = base_request("hmyv2_getStakingTransactionsCount", + params=[s0_validator["validator-addr"], "RECEIVED"], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 0, f"Expected account {s0_validator['validator-addr']} to have 0 received transactions" + + # Check v1, ALL + raw_response = base_request("hmy_getStakingTransactionsCount", + params=[s0_validator["validator-addr"], "ALL"], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {s0_validator['validator-addr']} to have 1 total transactions" + + # Check v1, ALL + raw_response = base_request("hmyv2_getStakingTransactionsCount", + params=[s0_validator["validator-addr"], "ALL"], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response == 1, f"Expected account {s0_validator['validator-addr']} to have 1 total transactions" + + +@txs.staking +def test_get_all_validator_information(s0_validator, s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + { + "validator": { + "bls-public-keys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "last-epoch-in-committee": 0, + "min-self-delegation": 10000000000000000000000, + "max-total-delegation": 10000000000000000000000000, + "rate": "0.100000000000000000", + "max-rate": "0.900000000000000000", + "max-change-rate": "0.050000000000000000", + "update-height": 4, + "name": "test", + "identity": "test0", + "website": "test", + "security-contact": "test", + "details": "test", + "creation-height": 4, + "address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegations": [ + { + "delegator-address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "undelegations": [] + } + ] + }, + "current-epoch-performance": { + "current-epoch-signing-percent": { + "current-epoch-signed": 0, + "current-epoch-to-sign": 0, + "current-epoch-signing-percentage": "0.000000000000000000" + } + }, + "metrics": None, + "total-delegation": 10000000000000000000000, + "currently-in-committee": True, + "epos-status": "currently elected", + "epos-winning-stake": None, + "booted-status": "not booted", + "active-status": "active", + "lifetime": { + "reward-accumulated": 0, + "blocks": { + "to-sign": 0, + "signed": 0 + }, + "apr": "0.000000000000000000", + "epoch-apr": None + } + } + ] + + # Check v1 + raw_response = base_request("hmy_getAllValidatorInformation", params=[0], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0, found_s1 = False, False + for validator in response: + if validator["validator"]["address"] == s0_validator["validator-addr"]: + found_s0 = True + _assert_validator_info(s0_validator, validator) + elif validator["validator"]["address"] == s1_validator["validator-addr"]: + found_s1 = True + _assert_validator_info(s1_validator, validator) + for delegation in validator["validator"]["delegations"]: + assert_no_null_in_list(delegation["undelegations"]) + assert found_s0 and found_s1, f"Expected to find validator information for " \ + f"{s0_validator['validator-addr']} and {s1_validator['validator-addr']}" + + # Check v2 + raw_response = base_request("hmyv2_getAllValidatorInformation", params=[0], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0, found_s1 = False, False + for validator in response: + if validator["validator"]["address"] == s0_validator["validator-addr"]: + found_s0 = True + _assert_validator_info(s0_validator, validator) + elif validator["validator"]["address"] == s1_validator["validator-addr"]: + found_s1 = True + _assert_validator_info(s1_validator, validator) + for delegation in validator["validator"]["delegations"]: + assert_no_null_in_list(delegation["undelegations"]) + assert found_s0 and found_s1, f"Expected to found validator information for " \ + f"{s0_validator['validator-addr']} and {s1_validator['validator-addr']}" + + +@txs.staking +def test_get_validator_information(s0_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "validator": { + "bls-public-keys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "last-epoch-in-committee": 0, + "min-self-delegation": 10000000000000000000000, + "max-total-delegation": 10000000000000000000000000, + "rate": "0.100000000000000000", + "max-rate": "0.900000000000000000", + "max-change-rate": "0.050000000000000000", + "update-height": 4, + "name": "test", + "identity": "test0", + "website": "test", + "security-contact": "test", + "details": "test", + "creation-height": 4, + "address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegations": [ + { + "delegator-address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "undelegations": [] + } + ] + }, + "current-epoch-performance": { + "current-epoch-signing-percent": { + "current-epoch-signed": 0, + "current-epoch-to-sign": 0, + "current-epoch-signing-percentage": "0.000000000000000000" + } + }, + "metrics": None, + "total-delegation": 10000000000000000000000, + "currently-in-committee": True, + "epos-status": "currently elected", + "epos-winning-stake": None, + "booted-status": "not booted", + "active-status": "active", + "lifetime": { + "reward-accumulated": 0, + "blocks": { + "to-sign": 0, + "signed": 0 + }, + "apr": "0.000000000000000000", + "epoch-apr": None + } + } + + # Check v1 + raw_response = base_request("hmy_getValidatorInformation", params=[s0_validator["validator-addr"]], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + _assert_validator_info(s0_validator, response) + for delegation in response["validator"]["delegations"]: + assert_no_null_in_list(delegation["undelegations"]) + + # Check v2 + raw_response = base_request("hmyv2_getValidatorInformation", params=[s0_validator["validator-addr"]], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + _assert_validator_info(s0_validator, response) + for delegation in response["validator"]["delegations"]: + assert_no_null_in_list(delegation["undelegations"]) + + +@txs.staking +def test_get_validator_information_by_block_number(s0_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "validator": { + "bls-public-keys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "last-epoch-in-committee": 0, + "min-self-delegation": 10000000000000000000000, + "max-total-delegation": 10000000000000000000000000, + "rate": "0.100000000000000000", + "max-rate": "0.900000000000000000", + "max-change-rate": "0.050000000000000000", + "update-height": 4, + "name": "test", + "identity": "test0", + "website": "test", + "security-contact": "test", + "details": "test", + "creation-height": 4, + "address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegations": [ + { + "delegator-address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "undelegations": [] + } + ] + }, + "current-epoch-performance": { + "current-epoch-signing-percent": { + "current-epoch-signed": 0, + "current-epoch-to-sign": 0, + "current-epoch-signing-percentage": "0.000000000000000000" + } + }, + "metrics": None, + "total-delegation": 10000000000000000000000, + "currently-in-committee": True, + "epos-status": "currently elected", + "epos-winning-stake": None, + "booted-status": "not booted", + "active-status": "active", + "lifetime": { + "reward-accumulated": 0, + "blocks": { + "to-sign": 0, + "signed": 0 + }, + "apr": "0.000000000000000000", + "epoch-apr": None + } + } + curr_block = blockchain.get_block_number(endpoint=endpoints[beacon_shard_id]) + + # Check v1 + raw_response = base_request("hmy_getValidatorInformationByBlockNumber", + params=[s0_validator["validator-addr"], hex(curr_block)], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + _assert_validator_info(s0_validator, response) + + # Check v2 + raw_response = base_request("hmyv2_getValidatorInformationByBlockNumber", + params=[s0_validator["validator-addr"], curr_block], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + _assert_validator_info(s0_validator, response) + + +@txs.staking +def test_get_all_validator_information_by_block_number(s0_validator, s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + { + "validator": { + "bls-public-keys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "last-epoch-in-committee": 0, + "min-self-delegation": 10000000000000000000000, + "max-total-delegation": 10000000000000000000000000, + "rate": "0.100000000000000000", + "max-rate": "0.900000000000000000", + "max-change-rate": "0.050000000000000000", + "update-height": 4, + "name": "test", + "identity": "test0", + "website": "test", + "security-contact": "test", + "details": "test", + "creation-height": 4, + "address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegations": [ + { + "delegator-address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "undelegations": [] + } + ] + }, + "current-epoch-performance": { + "current-epoch-signing-percent": { + "current-epoch-signed": 0, + "current-epoch-to-sign": 0, + "current-epoch-signing-percentage": "0.000000000000000000" + } + }, + "metrics": None, + "total-delegation": 10000000000000000000000, + "currently-in-committee": True, + "epos-status": "currently elected", + "epos-winning-stake": None, + "booted-status": "not booted", + "active-status": "active", + "lifetime": { + "reward-accumulated": 0, + "blocks": { + "to-sign": 0, + "signed": 0 + }, + "apr": "0.000000000000000000", + "epoch-apr": None + } + } + ] + curr_block = blockchain.get_block_number(endpoint=endpoints[beacon_shard_id]) + + # Check v1 + raw_response = base_request("hmy_getAllValidatorInformationByBlockNumber", params=[0, hex(curr_block)], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0, found_s1 = False, False + for validator in response: + if validator["validator"]["address"] == s0_validator["validator-addr"]: + found_s0 = True + _assert_validator_info(s0_validator, validator) + elif validator["validator"]["address"] == s1_validator["validator-addr"]: + found_s1 = True + _assert_validator_info(s1_validator, validator) + assert found_s0 and found_s1, f"Expected to found validator information for " \ + f"{s0_validator['validator-addr']} and {s0_validator['validator-addr']}" + + # Check v2 + raw_response = base_request("hmyv2_getAllValidatorInformationByBlockNumber", params=[0, curr_block], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0, found_s1 = False, False + for validator in response: + if validator["validator"]["address"] == s0_validator["validator-addr"]: + found_s0 = True + _assert_validator_info(s0_validator, validator) + elif validator["validator"]["address"] == s1_validator["validator-addr"]: + found_s1 = True + _assert_validator_info(s1_validator, validator) + assert found_s0 and found_s1, f"Expected to found validator information for " \ + f"{s0_validator['validator-addr']} and {s0_validator['validator-addr']}" + + +@txs.staking +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@pytest.mark.run(after="test_get_validator_information") +def test_get_elected_validator_addresses(s0_validator, s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + 'one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e', + 'one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts' + ] + + staking_epoch = blockchain.get_staking_epoch(endpoints[beacon_shard_id]) + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + val_0_info = staking.get_validator_information(s0_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + val_1_info = staking.get_validator_information(s1_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + s0_creation_epoch = int(blockchain.get_block_by_number(val_0_info["validator"]["creation-height"])["epoch"], 16) + s1_creation_epoch = int(blockchain.get_block_by_number(val_1_info["validator"]["creation-height"])["epoch"], 16) + + while curr_epoch <= s0_creation_epoch or curr_epoch <= s1_creation_epoch or curr_epoch < staking_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + + # Check v1 + raw_response = base_request("hmy_getElectedValidatorAddresses", params=[], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert s0_validator["validator-addr"] in response, f"Expected validator {s0_validator['validator-addr']} " \ + f"in elected validator list {response}" + #assert s1_validator["validator-addr"] in response, f"Expected validator {s1_validator['validator-addr']} " \ + # f"in elected validator list {response}" + + # Check v2 + raw_response = base_request("hmyv2_getElectedValidatorAddresses", params=[], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert s0_validator["validator-addr"] in response, f"Expected validator {s0_validator['validator-addr']} " \ + f"in elected validator list {response}" + #assert s1_validator["validator-addr"] in response, f"Expected validator {s1_validator['validator-addr']} " \ + # f"in elected validator list {response}" + + +@txs.staking +@pytest.mark.run(after="test_delegation") +def test_get_delegations_by_delegator(s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + { + "validator_address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegator_address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "Undelegations": [] + }, + ] + val_addr = s1_validator["validator-addr"] + validator_info = staking.get_validator_information(val_addr, endpoint=endpoints[beacon_shard_id]) + + for delegator in validator_info["validator"]["delegations"]: + # Check v1 + del_addr = delegator["delegator-address"] + raw_response = base_request("hmy_getDelegationsByDelegator", params=[del_addr], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert_no_null_in_list(response) + found_validator = False + for del_delegator in response: + assert_no_null_in_list(del_delegator["Undelegations"]) + if del_delegator["validator_address"] == val_addr: + found_validator = True + assert del_addr == del_delegator["delegator_address"], f"Expected delegator address {del_addr}, " \ + f"got {del_delegator['delegator_address']}" + assert found_validator, f"Expected to found validator {val_addr} in {json.dumps(response, indent=2)}" + + # Check v2 + raw_response = base_request("hmyv2_getDelegationsByDelegator", params=[del_addr], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert_no_null_in_list(response) + found_validator = False + for del_delegator in response: + assert_no_null_in_list(del_delegator["Undelegations"]) + if del_delegator["validator_address"] == val_addr: + found_validator = True + assert del_addr == del_delegator["delegator_address"], f"Expected delegator address {del_addr}, " \ + f"got {del_delegator['delegator_address']}" + assert found_validator, f"Expected to found validator {val_addr} in {json.dumps(response, indent=2)}" + + +@txs.staking +@mutually_exclusive_test(scope=_mutex_scope) +@pytest.mark.run(after="test_delegation") +def test_get_delegations_by_delegator_by_block_number(s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + { + "validator_address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegator_address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "Undelegations": [] + }, + ] + curr_block = blockchain.get_block_number(endpoint=endpoints[beacon_shard_id]) + val_addr = s1_validator["validator-addr"] + validator_info = staking.get_validator_information(val_addr, endpoint=endpoints[beacon_shard_id]) + + for delegator in validator_info["validator"]["delegations"]: + # Check v1 + del_addr = delegator["delegator-address"] + raw_response = base_request("hmy_getDelegationsByDelegatorByBlockNumber", params=[del_addr, hex(curr_block)], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert_no_null_in_list(response) + found_validator = False + for del_delegator in response: + assert_no_null_in_list(del_delegator["Undelegations"]) + if del_delegator["validator_address"] == val_addr: + found_validator = True + assert del_addr == del_delegator["delegator_address"], f"Expected delegator address {del_addr}, " \ + f"got {del_delegator['delegator_address']}" + assert found_validator, f"Expected to found validator {val_addr} in {json.dumps(response, indent=2)}" + + # Check v2 + raw_response = base_request("hmyv2_getDelegationsByDelegatorByBlockNumber", params=[del_addr, curr_block], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert_no_null_in_list(response) + found_validator = False + for del_delegator in response: + assert_no_null_in_list(del_delegator["Undelegations"]) + if del_delegator["validator_address"] == val_addr: + found_validator = True + assert del_addr == del_delegator["delegator_address"], f"Expected delegator address {del_addr}, " \ + f"got {del_delegator['delegator_address']}" + assert found_validator, f"Expected to found validator {val_addr} in {json.dumps(response, indent=2)}" + + +@txs.staking +@mutually_exclusive_test(scope=_mutex_scope) +@pytest.mark.run(after="test_delegation") +def test_get_delegations_by_validator(s1_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = [ + { + "validator_address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "delegator_address": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "amount": 10000000000000000000000, + "reward": 0, + "Undelegations": [] + }, + ] + val_addr = s1_validator["validator-addr"] + validator_info = staking.get_validator_information(val_addr, endpoint=endpoints[beacon_shard_id]) + val_del_addrs = {d["delegator-address"] for d in validator_info["validator"]["delegations"]} + + # Check v1 + raw_response = base_request("hmy_getDelegationsByValidator", params=[val_addr], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert_no_null_in_list(response) + for del_delegator in response: + assert_no_null_in_list(del_delegator["Undelegations"]) + del_val_addr, del_del_addr = del_delegator["validator_address"], del_delegator["delegator_address"] + assert del_val_addr == val_addr, f"Expected validator addr {val_addr}, got {del_val_addr}" + assert del_del_addr in val_del_addrs, f"Expected delegator addr {val_addr} in {val_del_addrs}" + + # Check v2 + raw_response = base_request("hmyv2_getDelegationsByValidator", params=[val_addr], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for del_delegator in response: + del_val_addr, del_del_addr = del_delegator["validator_address"], del_delegator["delegator_address"] + assert del_val_addr == val_addr, f"Expected validator addr {val_addr}, got {del_val_addr}" + assert del_del_addr in val_del_addrs, f"Expected delegator addr {val_addr} in {val_del_addrs}" + + +@txs.staking +def test_get_current_utility_metrics(s0_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "AccumulatorSnapshot": 5768000000000000000000, + "CurrentStakedPercentage": "0.000004311108610723", + "Deviation": "0.349995688891389277", + "Adjustment": "13999827555655571080.000000000000000000" + } + + # Check v1 + raw_response = base_request("hmy_getCurrentUtilityMetrics", params=[], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + # Check v2 + raw_response = base_request("hmyv2_getCurrentUtilityMetrics", params=[], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +@txs.staking +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@pytest.mark.run(after="test_get_validator_information") +@pytest.mark.skip(reason="This test is flaky and needs to be fixed") +def test_get_median_raw_stake_snapshot(s0_validator): + """ + Note that v1 & v2 have the same responses. + + Use shard 0 endpoint, NOT beacon endpoint as we are checking with `s0_validator` + """ + reference_response = { + "epos-median-stake": "10000000000000000000000.000000000000000000", + "max-external-slots": 6, + "epos-slot-winners": [ + { + "slot-owner": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "bls-public-key": "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c", + "raw-stake": "10000000000000000000000.000000000000000000", + "eposed-stake": "10000000000000000000000.000000000000000000" + } + ], + "epos-slot-candidates": [ + { + "stake": 10000000000000000000000, + "keys-at-auction": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "percentage-of-total-auction-stake": "1.000000000000000000", + "stake-per-key": 10000000000000000000000, + "validator": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e" + } + ] + } + + staking_epoch = blockchain.get_staking_epoch(endpoints[beacon_shard_id]) + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[0])["epoch"] + val_0_info = staking.get_validator_information(s0_validator["validator-addr"], endpoint=endpoints[0]) + s0_creation_epoch = int(blockchain.get_block_by_number(val_0_info["validator"]["creation-height"])["epoch"], 16) + + + while curr_epoch <= s0_creation_epoch or curr_epoch < staking_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + + # First block of an epoch does not have correct snapshot, wait for next block. + curr_block = blockchain.get_latest_header(endpoint=endpoints[0])["blockNumber"] + prev_block_epoch = int(blockchain.get_block_by_number(curr_block - 1)["epoch"], 16) + while prev_block_epoch != curr_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_block = blockchain.get_latest_header(endpoint=endpoints[0])["blockNumber"] + prev_block_epoch = int(blockchain.get_block_by_number(curr_block - 1)["epoch"], 16) + + # Check v1 + raw_response = base_request("hmy_getMedianRawStakeSnapshot", params=[], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0_winner, found_s0_candidate = False, False + for val in response["epos-slot-winners"]: + if val["slot-owner"] == s0_validator["validator-addr"]: + found_s0_winner = True + break + assert found_s0_winner, f"Expected validator {s0_validator['validator-addr']} to win election" + for val in response["epos-slot-candidates"]: + if val["validator"] == s0_validator["validator-addr"]: + found_s0_candidate = True + break + assert found_s0_candidate, f"Expected validator {s0_validator['validator-addr']} to be candidate for next epoch" + + # Check v2 + raw_response = base_request("hmyv2_getMedianRawStakeSnapshot", params=[], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0_winner, found_s0_candidate = False, False + for val in response["epos-slot-winners"]: + if val["slot-owner"] == s0_validator["validator-addr"]: + found_s0_winner = True + break + assert found_s0_winner, f"Expected validator {s0_validator['validator-addr']} to win election" + for val in response["epos-slot-candidates"]: + if val["validator"] == s0_validator["validator-addr"]: + found_s0_candidate = True + break + assert found_s0_candidate, f"Expected validator {s0_validator['validator-addr']} to be candidate for next epoch" + + +@txs.staking +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@pytest.mark.run(after="test_get_median_raw_stake_snapshot") +def test_get_super_committees(s0_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "previous": { + "quorum-deciders": { + "shard-0": { + "policy": "SuperMajorityStake", + "count": 7, + "external-validator-slot-count": 1, + "committee-members": [ + { + "is-harmony-slot": True, + "earning-account": "one1spshr72utf6rwxseaz339j09ed8p6f8ke370zj", + "bls-public-key": "2d61379e44a772e5757e27ee2b3874254f56073e6bd226eb8b160371cc3c18b8c4977bd3dcb71fd57dc62bf0e143fd08", + "voting-power-unnormalized": "0.166666666666666666", + "voting-power-%": "0.113333333333333333" + }, + ], + "hmy-voting-power": "0.679999999999999998", + "staked-voting-power": "0.320000000000000002", + "total-raw-stake": "10000000000000000000000.000000000000000000", + "total-effective-stake": "10000000000000000000000.000000000000000000" + }, + "shard-1": { + "policy": "SuperMajorityStake", + "count": 6, + "external-validator-slot-count": 0, + "committee-members": [ + { + "is-harmony-slot": True, + "earning-account": "one1m6m0ll3q7ljdqgmth2t5j7dfe6stykucpj2nr5", + "bls-public-key": "40379eed79ed82bebfb4310894fd33b6a3f8413a78dc4d43b98d0adc9ef69f3285df05eaab9f2ce5f7227f8cb920e809", + "voting-power-unnormalized": "0.166666666666666666", + "voting-power-%": "0.113333333333333333" + }, + ], + "hmy-voting-power": "0.679999999999999998", + "staked-voting-power": "0.000000000000000000", + "total-raw-stake": "0.000000000000000000", + "total-effective-stake": "0.000000000000000000" + } + }, + "external-slot-count": 6, + "epos-median-stake": "10000000000000000000000.000000000000000000" + }, + "current": { + "quorum-deciders": { + "shard-0": { + "policy": "SuperMajorityStake", + "count": 7, + "external-validator-slot-count": 1, + "committee-members": [ + { + "is-harmony-slot": True, + "earning-account": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "bls-public-key": "65f55eb3052f9e9f632b2923be594ba77c55543f5c58ee1454b9cfd658d25e06373b0f7d42a19c84768139ea294f6204", + "voting-power-unnormalized": "0.166666666666666666", + "voting-power-%": "0.113333333333333333" + }, + ], + "hmy-voting-power": "0.679999999999999998", + "staked-voting-power": "0.320000000000000002", + "total-raw-stake": "10000000000000000000000.000000000000000000", + "total-effective-stake": "10000000000000000000000.000000000000000000" + }, + "shard-1": { + "policy": "SuperMajorityStake", + "count": 6, + "external-validator-slot-count": 0, + "committee-members": [ + { + "is-harmony-slot": True, + "earning-account": "one1m6m0ll3q7ljdqgmth2t5j7dfe6stykucpj2nr5", + "bls-public-key": "40379eed79ed82bebfb4310894fd33b6a3f8413a78dc4d43b98d0adc9ef69f3285df05eaab9f2ce5f7227f8cb920e809", + "voting-power-unnormalized": "0.166666666666666666", + "voting-power-%": "0.113333333333333333" + }, + ], + "hmy-voting-power": "0.679999999999999998", + "staked-voting-power": "0.000000000000000000", + "total-raw-stake": "0.000000000000000000", + "total-effective-stake": "0.000000000000000000" + } + }, + "external-slot-count": 6, + "epos-median-stake": "10000000000000000000000.000000000000000000" + } + } + + staking_epoch = blockchain.get_staking_epoch(endpoints[beacon_shard_id]) + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + val_0_info = staking.get_validator_information(s0_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + s0_creation_epoch = int(blockchain.get_block_by_number(val_0_info["validator"]["creation-height"])["epoch"], 16) + + while curr_epoch <= s0_creation_epoch or curr_epoch < staking_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[0])["epoch"] + + # Check v1 + raw_response = base_request("hmy_getSuperCommittees", params=[], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_validator, found_key = False, False + for member in response["current"]["quorum-deciders"]["shard-0"]["committee-members"]: + if member["earning-account"] == s0_validator["validator-addr"]: + found_validator = True + if member["bls-public-key"] == s0_validator["pub-bls-key"]: + found_key = True + assert found_validator, f"Expected to find validator {s0_validator['validator-addr']} in current committee" + assert found_key, f"Expected to pub bls key {s0_validator['bls-public-key']} in current committee" + + # Check v2 + raw_response = base_request("hmyv2_getSuperCommittees", params=[], endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_validator, found_key = False, False + for member in response["current"]["quorum-deciders"]["shard-0"]["committee-members"]: + if member["earning-account"] == s0_validator["validator-addr"]: + found_validator = True + if member["bls-public-key"] == s0_validator["pub-bls-key"]: + found_key = True + assert found_validator, f"Expected to find validator {s0_validator['validator-addr']} in current committee" + assert found_key, f"Expected to pub bls key {s0_validator['bls-public-key']} in current committee" + + +@txs.staking +def test_get_staking_network_info(s0_validator): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "total-supply": "12600000000.000000000000000000", + "circulating-supply": "6842781705.882339000000000000", + "epoch-last-block": 59, + "total-staking": 10000000000000000000000, + "median-raw-stake": "10000000000000000000000.000000000000000000" + } + + # Check v1 + raw_response = base_request("hmy_getStakingNetworkInfo", params=[], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + # Check v2 + raw_response = base_request("hmyv2_getStakingNetworkInfo", params=[], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +@txs.staking +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +def test_get_validator_keys(s0_validator): + """ + Note that v1 & v2 have the same responses. + + Use shard 0 endpoint, NOT beacon endpoint as we are checking with `s0_validator` + """ + reference_response = [ + "65f55eb3052f9e9f632b2923be594ba77c55543f5c58ee1454b9cfd658d25e06373b0f7d42a19c84768139ea294f6204", + ] + + staking_epoch = blockchain.get_staking_epoch(endpoints[beacon_shard_id]) + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[0])["epoch"] + val_0_info = staking.get_validator_information(s0_validator["validator-addr"], endpoint=endpoints[0]) + s0_creation_epoch = int(blockchain.get_block_by_number(val_0_info["validator"]["creation-height"])["epoch"], 16) + + while curr_epoch <= s0_creation_epoch or curr_epoch < staking_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + + # Check v1 + raw_response = base_request("hmy_getValidatorKeys", params=[curr_epoch], + endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert s0_validator["pub-bls-key"] in response, f"Expected pub bls key {s0_validator['pub-bls-key']} in {response}" + + # Check v1 + raw_response = base_request("hmyv2_getValidatorKeys", params=[curr_epoch], + endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert s0_validator["pub-bls-key"] in response, f"Expected pub bls key {s0_validator['pub-bls-key']} in {response}" + + +@txs.staking +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@pytest.mark.skip(reason="This test is flaky and needs to be fixed") +def test_get_validators_v1(s0_validator, s1_validator): + reference_response = { + "shardID": 0, + "validators": [ + { + "address": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "balance": "0x252c53eaca3b23bb3" + }, + ] + } + + staking_epoch = blockchain.get_staking_epoch(endpoints[beacon_shard_id]) + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + val_0_info = staking.get_validator_information(s0_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + val_1_info = staking.get_validator_information(s1_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + s0_creation_epoch = int(blockchain.get_block_by_number(val_0_info["validator"]["creation-height"])["epoch"], 16) + s1_creation_epoch = int(blockchain.get_block_by_number(val_1_info["validator"]["creation-height"])["epoch"], 16) + + while curr_epoch <= s0_creation_epoch or curr_epoch <= s1_creation_epoch or curr_epoch < staking_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + + raw_response = base_request("hmy_getValidators", params=[curr_epoch], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0, found_s1 = False, False + for val in response["validators"]: + if val["address"] == s0_validator["validator-addr"]: + found_s0 = True + if val["address"] == s1_validator["validator-addr"]: + found_s1 = True + assert found_s0 and found_s1, f"Expected to find validator information for " \ + f"{s0_validator['validator-addr']} and {s1_validator['validator-addr']}" + + +@txs.staking +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@pytest.mark.skip(reason="This test is flaky and needs to be fixed") +def test_get_validators_v2(s0_validator, s1_validator): + reference_response = { + "shardID": 0, + "validators": [ + { + "address": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "balance": 42857730340142857139 + }, + ] + } + + staking_epoch = blockchain.get_staking_epoch(endpoints[beacon_shard_id]) + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + val_0_info = staking.get_validator_information(s0_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + val_1_info = staking.get_validator_information(s1_validator["validator-addr"], endpoint=endpoints[beacon_shard_id]) + s0_creation_epoch = int(blockchain.get_block_by_number(val_0_info["validator"]["creation-height"])["epoch"], 16) + s1_creation_epoch = int(blockchain.get_block_by_number(val_1_info["validator"]["creation-height"])["epoch"], 16) + + while curr_epoch <= s0_creation_epoch or curr_epoch <= s1_creation_epoch or curr_epoch < staking_epoch: + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + curr_epoch = blockchain.get_latest_header(endpoint=endpoints[beacon_shard_id])["epoch"] + + raw_response = base_request("hmyv2_getValidators", params=[curr_epoch], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + found_s0, found_s1 = False, False + for val in response["validators"]: + if val["address"] == s0_validator["validator-addr"]: + found_s0 = True + if val["address"] == s1_validator["validator-addr"]: + found_s1 = True + assert found_s0 and found_s1, f"Expected to find validator information for " \ + f"{s0_validator['validator-addr']} and {s0_validator['validator-addr']}" + + +@txs.staking +@pytest.mark.run('first') +def test_pending_staking_transactions_v1(): + stx = { # Create validator tx + "validator-addr": "one13v9m45m6yk9qmmcgyq603ucy0wdw9lfsxzsj9d", + "delegator-addr": "one13v9m45m6yk9qmmcgyq603ucy0wdw9lfsxzsj9d", + "name": "test", + "identity": "test2", + "website": "test", + "security-contact": "test", + "details": "test", + "rate": 0.1, + "max-rate": 0.9, + "max-change-rate": 0.05, + "min-self-delegation": 10000, + "max-total-delegation": 10000000, + "amount": 10000, + "pub-bls-key": "1ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8a", + "hash": "0x27e40b843f12f216e301e9d03d5691cda04fd152ca739e3bfece2aa66c508bb8", + "nonce": "0x0", + "signed-raw-tx": "0xf9015880f90106948b0bbad37a258a0def082034f8f3047b9ae2fd30da8474657374857465737432847465737484746573748474657374ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500008a021e19e0c9bab24000008b084595161401484a000000f1b01ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8af862b8603ee56bf8d64e4472b4273a4c10e12d498e8a0ac01df613e44ccf7c211bbed865fc192c93b8f23a3b67f352153921e304380503169a47746ba61ea9a720dad734b07ecc997e6e0cabecba00c5a73f43b3773ec2b51f67023102aedd2deff1048a8a021e19e0c9bab2400000808506fc23ac008350ef0828a0c10e91884acbb4ce01d4fd960c69287e9d60a6e8dbca13fe4e74a2557c8eca99a02648d27fd5162dfb5d76b6f87c0743960b1634141f98806fc3f0f43035244edc" + } + reference_response = [ + { + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": None, + "from": "one13v9m45m6yk9qmmcgyq603ucy0wdw9lfsxzsj9d", + "timestamp": "0x0", + "gas": "0x512204", + "gasPrice": "0x3b9aca00", + "hash": "0xf16668d7e39f01fd15c40e515ece370af1c80f7588bffd7c53932768a0ebba2e", + "nonce": "0x0", + "transactionIndex": "0x0", + "v": "0x27", + "r": "0x2eeadff25df33d13eb95288006435e06a65ad979bf24b9cbd151c696df5b84e3", + "s": "0x16e9fa32ddad438936ba2ac837cc8ac102aeec519198fa4516cfac7032df313c", + "type": "CreateValidator", + "msg": None + } + ] + reference_create_validator_msg = { + "amount": "0x21e19e0c9bab2400000", + "commissionRate": "0x16345785d8a0000", + "details": "test", + "identity": "test2", + "maxChangeRate": "0xb1a2bc2ec50000", + "maxCommissionRate": "0xc7d713b49da0000", + "maxTotalDelegation": "0x84595161401484a000000", + "minSelfDelegation": "0x21e19e0c9bab2400000", + "name": "test", + "securityContact": "test", + "slotPubKeys": [ + "1ffbdd82dca92a42330d3b119ea007de74c81d446c3b396dd9e1ba1f9fa95a43125cd16c4f79dd1d505a5eb6a22e7c8a" + ], + "validatorAddress": "one13v9m45m6yk9qmmcgyq603ucy0wdw9lfsxzsj9d", + "website": "test" + } + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == stx["validator-addr"] and tx["to-shard"] == beacon_shard_id: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test staking transaction from address {stx['validator-addr']} " + f"not found in set of initially funded accounts (or not founded on s{beacon_shard_id})") + + if get_staking_transaction(stx["hash"]) is not None: + pytest.skip(f"Test staking transaction (hash {stx['hash']}) already present on chain...") + + send_staking_transaction(stx, confirm_submission=True) + + start_time = time.time() + while time.time() - start_time <= tx_timeout: + raw_response = base_request("hmy_pendingStakingTransactions", endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for pending_tx in response: + if pending_tx["hash"] == stx["hash"]: + assert pending_tx["type"] == "CreateValidator" + assert_valid_json_structure(reference_create_validator_msg, pending_tx["msg"]) + return + + raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(stx, indent=2)}") + + +@txs.staking +@pytest.mark.run('first') +def test_pending_staking_transactions_v2(): + stx = { # Create validator tx + "validator-addr": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + "delegator-addr": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + "name": "test", + "identity": "test3", + "website": "test", + "security-contact": "test", + "details": "test", + "rate": 0.1, + "max-rate": 0.9, + "max-change-rate": 0.05, + "min-self-delegation": 10000, + "max-total-delegation": 10000000, + "amount": 10000, + "pub-bls-key": "5a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97", + "hash": "0x28116f87be9be8dea7bb0b26f5a8deb31ab96c91e5d8e3ce3d8dc780d08e4b87", + "nonce": "0x0", + "signed-raw-tx": "0xf9015880f90106948ef8092bc9c36854246cf384ce778145ace6385fda8474657374857465737433847465737484746573748474657374ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500008a021e19e0c9bab24000008b084595161401484a000000f1b05a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97f862b8607eee5f5d8e07fdf53f700281fb290c378ffca5167d1c8443fd1f42408e51af1f70e3f910361da2d88a64a612afa0ae00c6fbe396333e449d32120f2702bb29032e07d81c57ed5b0722eaa9bcce9cabf6eaf22ce513676fcf5d2d06a6998f4a0e8a021e19e0c9bab2400000808506fc23ac008350ef0828a08bc729219637ca0ff3286289484830b0a91428da80de43b2d8e3c0330346ff04a031aed5e2b812a9c689d7bc75abd53effb36f38cc356bcf061465dd8f545288de" + } + reference_response = [ + { + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": None, + "from": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + "timestamp": 0, + "gas": 5317124, + "gasPrice": 1000000000, + "hash": "0x6e54fc7102daa31372027912b7f441ab9b9acafb9fa93b72dc9380321bacdbe2", + "nonce": 0, + "transactionIndex": 0, + "v": "0x27", + "r": "0xe03993350ed72c70198bbb9b0c962eba1ba08c6c46f66c50a878f84970120941", + "s": "0x421342afa7dd527edadfb8fc0b3b80c41ba3fcd390cc2ff95bc18b89c58850ca", + "type": "CreateValidator", + "msg": None + } + ] + reference_create_validator_msg = { + "amount": 10000000000000000000000, + "commissionRate": 100000000000000000, + "details": "test", + "identity": "test3", + "maxChangeRate": 50000000000000000, + "maxCommissionRate": 900000000000000000, + "maxTotalDelegation": 10000000000000000000000000, + "minSelfDelegation": 10000000000000000000000, + "name": "test", + "securityContact": "test", + "slotPubKeys": [ + "5a18d4aa3e6aff4835f07588ae66be19684476d38799f63e54c6b5732fad1e86dce7458b1c295404fb54a0d61e50bb97" + ], + "validatorAddress": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + "website": "test" + } + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == stx["validator-addr"] and tx["to-shard"] == beacon_shard_id: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test staking transaction from address {stx['validator-addr']} " + f"not found in set of initially funded accounts (or not founded on s{beacon_shard_id})") + + if get_staking_transaction(stx["hash"]) is not None: + pytest.skip(f"Test staking transaction (hash {stx['hash']}) already present on chain...") + + send_staking_transaction(stx, confirm_submission=True) + + start_time = time.time() + while time.time() - start_time <= tx_timeout: + raw_response = base_request("hmyv2_pendingStakingTransactions", endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for pending_tx in response: + if pending_tx["hash"] == stx["hash"]: + assert pending_tx["type"] == "CreateValidator" + assert_valid_json_structure(reference_create_validator_msg, pending_tx["msg"]) + return + + raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(stx, indent=2)}") + + +@txs.staking +@mutually_exclusive_test(scope=_mutex_scope) +def test_get_blocks_v1(s0_validator): + """ + Note: param options for 'withSigners' will NOT return any sensical data + in staking epoch (since it returns ONE addresses) and is subject to removal, thus is not tested here. + """ + reference_response_blk = { + "difficulty": 0, + "epoch": "0x1", + "extraData": "0x", + "gasLimit": "0x4c4b400", + "gasUsed": "0x5121c4", + "hash": "0xc0438fb59641cf000ddede158cf3707b6b96f2fbf7eaf40386eb91a0dc4305a4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": "0xb", + "parentHash": "0x57b4221951b61025eccea748c3a67dc2f1dafa9db278ac4d67135061432de6d0", + "receiptsRoot": "0x37f9bea40135162a9eb2164266b2152a3909ee94dd2f908cdb091afb90724e1e", + "size": "0x3fd", + "stakingTransactions": [], + "stateRoot": "0x33109119529b1d282909975ce846a3eeb1b76681d7beebfa5cf79adfe4a1c4d7", + "timestamp": "0x5f11a7a2", + "transactions": [], + "transactionsRoot": "0xf4ab626bfc3bf9781ddef818f85cc81c345010b7b6abaeb27d0237c8a1ee1ac5", + "uncles": [], + "viewID": "0xb" + } + reference_staking_response = { + "blockHash": "0xc0438fb59641cf000ddede158cf3707b6b96f2fbf7eaf40386eb91a0dc4305a4", + "blockNumber": "0xb", + "from": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "timestamp": "0x5f11a7a2", + "gas": "0x5121c4", + "gasPrice": "0x3b9aca00", + "hash": "0xf80460f1ad041a0a0e841da717fc5b7959b1a7e9a0ce9a25cd70c0ce40d5ff26", + "nonce": "0x0", + "transactionIndex": "0x0", + "v": "0x27", + "r": "0x2348daabe696c4370379b9102dd85da6d4fed52f0f511ff0448a21c001ee75a7", + "s": "0x1a67f9f40e0de02b50d5d7295f200fea7f950c1b59aa7efa8d225294c4fdbc5e", + "type": "CreateValidator", + "msg": None + } + reference_create_validator_msg = { + "amount": "0x21e19e0c9bab2400000", + "commissionRate": "0x16345785d8a0000", + "details": "test", + "identity": "test0", + "maxChangeRate": "0xb1a2bc2ec50000", + "maxCommissionRate": "0xc7d713b49da0000", + "maxTotalDelegation": "0x84595161401484a000000", + "minSelfDelegation": "0x21e19e0c9bab2400000", + "name": "test", + "securityContact": "test", + "slotPubKeys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "validatorAddress": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "website": "test" + } + + init_tx = get_staking_transaction(s0_validator["hash"]) + start_blk, end_blk = hex(max(0, int(init_tx["blockNumber"], 16) - 2)), init_tx["blockNumber"] + raw_response = base_request("hmy_getBlocks", + params=[start_blk, end_blk, { + "fullTx": True, + "inclStaking": True + }], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + for blk in response: + assert_valid_json_structure(reference_response_blk, blk) + for stx in blk["stakingTransactions"]: + assert_valid_json_structure(reference_staking_response, stx) + if stx["hash"] == s0_validator["hash"]: + assert stx["type"] == "CreateValidator" + assert_valid_json_structure(reference_create_validator_msg, stx["msg"]) + assert len(response[-1]["stakingTransactions"]) > 0, "Expected staking transactions on last block" + start_num, end_num = int(start_blk, 16), int(end_blk, 16) + for blk in response: + blk_num = int(blk["number"], 16) + assert start_num <= blk_num <= end_num, f"Got block number {blk_num}, which is not in range [{start_num},{end_num}]" + + +@txs.staking +@mutually_exclusive_test(scope=_mutex_scope) +def test_get_blocks_v2(s0_validator): + """ + Only difference in param of RPC is hex string in v1 and decimal in v2. + + Note: param options for 'withSigners' will NOT return any sensical data + in staking epoch (since it returns ONE addresses) and is subject to removal, thus is not tested here. + """ + reference_response_blk = { + "difficulty": 0, + "epoch": 1, + "extraData": "0x", + "gasLimit": 80000000, + "gasUsed": 5317060, + "hash": "0xc0438fb59641cf000ddede158cf3707b6b96f2fbf7eaf40386eb91a0dc4305a4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": 0, + "number": 11, + "parentHash": "0x57b4221951b61025eccea748c3a67dc2f1dafa9db278ac4d67135061432de6d0", + "receiptsRoot": "0x37f9bea40135162a9eb2164266b2152a3909ee94dd2f908cdb091afb90724e1e", + "size": 1021, + "stakingTransactions": [], + "stateRoot": "0x33109119529b1d282909975ce846a3eeb1b76681d7beebfa5cf79adfe4a1c4d7", + "timestamp": 1594992546, + "transactions": [], + "transactionsRoot": "0xf4ab626bfc3bf9781ddef818f85cc81c345010b7b6abaeb27d0237c8a1ee1ac5", + "uncles": [], + "viewID": 11 + } + reference_staking_response = { + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": None, + "from": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + "timestamp": 0, + "gas": 5317124, + "gasPrice": 1000000000, + "hash": "0x6e54fc7102daa31372027912b7f441ab9b9acafb9fa93b72dc9380321bacdbe2", + "nonce": 0, + "transactionIndex": 0, + "v": "0x27", + "r": "0xe03993350ed72c70198bbb9b0c962eba1ba08c6c46f66c50a878f84970120941", + "s": "0x421342afa7dd527edadfb8fc0b3b80c41ba3fcd390cc2ff95bc18b89c58850ca", + "type": "CreateValidator", + "msg": None + } + reference_create_validator_msg = { + "amount": 10000000000000000000000, + "commissionRate": 100000000000000000, + "details": "test", + "identity": "test3", + "maxChangeRate": 50000000000000000, + "maxCommissionRate": 900000000000000000, + "maxTotalDelegation": 10000000000000000000000000, + "minSelfDelegation": 10000000000000000000000, + "name": "test", + "securityContact": "test", + "slotPubKeys": [ + "29cdd2ea5ef25bfee0bbc649065ceb2d0e19cc25f42541154eca69c0ff923971e20352fbfeeac5d17f8f6c6fc5871e88" + ], + "validatorAddress": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + "website": "test" + } + + init_tx = get_staking_transaction(s0_validator["hash"]) + start_blk, end_blk = max(0, int(init_tx["blockNumber"], 16) - 2), int(init_tx["blockNumber"], 16) + raw_response = base_request("hmyv2_getBlocks", + params=[start_blk, end_blk, { + "fullTx": True, + "inclStaking": True + }], + endpoint=endpoints[beacon_shard_id]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + for blk in response: + assert_valid_json_structure(reference_response_blk, blk) + for stx in blk["stakingTransactions"]: + assert_valid_json_structure(reference_staking_response, stx) + if stx["hash"] == s0_validator["hash"]: + assert stx["type"] == "CreateValidator" + assert_valid_json_structure(reference_create_validator_msg, stx["msg"]) + assert len(response[-1]["stakingTransactions"]) > 0, "Expected staking transactions on last block" + for blk in response: + assert start_blk <= blk[ + "number"] <= end_blk, f"Got block number {blk['number']}, which is not in range [{start_blk},{end_blk}]" + + +@txs.staking +def test_get_staking_transaction_history_v1(s0_validator): + """ + No staking transactions for the 'to' account of `account_test_tx`. + + This method may not be implemented, skip if this is the case + """ + reference_response = { + "staking_transactions": [ + { + "blockHash": "0xc0438fb59641cf000ddede158cf3707b6b96f2fbf7eaf40386eb91a0dc4305a4", + "blockNumber": "0xb", + "from": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "timestamp": "0x5f11a7a2", + "gas": "0x5121c4", + "gasPrice": "0x3b9aca00", + "hash": "0xf80460f1ad041a0a0e841da717fc5b7959b1a7e9a0ce9a25cd70c0ce40d5ff26", + "nonce": "0x0", + "transactionIndex": "0x0", + "v": "0x27", + "r": "0x2348daabe696c4370379b9102dd85da6d4fed52f0f511ff0448a21c001ee75a7", + "s": "0x1a67f9f40e0de02b50d5d7295f200fea7f950c1b59aa7efa8d225294c4fdbc5e", + "type": "CreateValidator", + "msg": None + }, + ] + } + reference_create_validator_msg = { + "amount": "0x21e19e0c9bab2400000", + "commissionRate": "0x16345785d8a0000", + "details": "test", + "identity": "test0", + "maxChangeRate": "0xb1a2bc2ec50000", + "maxCommissionRate": "0xc7d713b49da0000", + "maxTotalDelegation": "0x84595161401484a000000", + "minSelfDelegation": "0x21e19e0c9bab2400000", + "name": "test", + "securityContact": "test", + "slotPubKeys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "validatorAddress": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "website": "test" + } + reference_response_short = { + "staking_transactions": [ + "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", + ] + } + + try: + raw_response = base_request("hmy_getStakingTransactionsHistory", + params=[{ + "address": s0_validator["validator-addr"], + "pageIndex": 0, + "pageSize": 1000, + "fullTx": False, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response_short, response) + + raw_response = base_request("hmy_getStakingTransactionsHistory", + params=[{ + "address": s0_validator["validator-addr"], + "pageIndex": 0, + "pageSize": 1000, + "fullTx": True, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for stx in response["staking_transactions"]: + if stx["hash"] == s0_validator["hash"]: + assert stx["type"] == "CreateValidator" + assert_valid_json_structure(reference_create_validator_msg, stx["msg"]) + except Exception as e: + pytest.skip(traceback.format_exc()) + pytest.skip(f"Exception: {e}") + + +@txs.staking +def test_get_staking_transaction_history_v2(s0_validator): + """ + No staking transactions for the 'to' account of `account_test_tx`. + """ + reference_response = { + "staking_transactions": [ + { + "blockHash": "0xc0438fb59641cf000ddede158cf3707b6b96f2fbf7eaf40386eb91a0dc4305a4", + "blockNumber": 11, + "from": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "timestamp": 1594992546, + "gas": 5317060, + "gasPrice": 1000000000, + "hash": "0xf80460f1ad041a0a0e841da717fc5b7959b1a7e9a0ce9a25cd70c0ce40d5ff26", + "nonce": 0, + "transactionIndex": 0, + "v": "0x27", + "r": "0x2348daabe696c4370379b9102dd85da6d4fed52f0f511ff0448a21c001ee75a7", + "s": "0x1a67f9f40e0de02b50d5d7295f200fea7f950c1b59aa7efa8d225294c4fdbc5e", + "type": "CreateValidator", + "msg": None + }, + ] + } + reference_create_validator_msg = { + "amount": 10000000000000000000000, + "commissionRate": 100000000000000000, + "details": "test", + "identity": "test0", + "maxChangeRate": 50000000000000000, + "maxCommissionRate": 900000000000000000, + "maxTotalDelegation": 10000000000000000000000000, + "minSelfDelegation": 10000000000000000000000, + "name": "test", + "securityContact": "test", + "slotPubKeys": [ + "4f41a37a3a8d0695dd6edcc58142c6b7d98e74da5c90e79b587b3b960b6a4f5e048e6d8b8a000d77a478d44cd640270c" + ], + "validatorAddress": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + "website": "test" + } + reference_response_short = { + "staking_transactions": [ + "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", + ] + } + + raw_response = base_request("hmyv2_getStakingTransactionsHistory", + params=[{ + "address": s0_validator["validator-addr"], + "pageIndex": 0, + "pageSize": 1000, + "fullTx": False, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response_short, response) + + raw_response = base_request("hmyv2_getStakingTransactionsHistory", + params=[{ + "address": s0_validator["validator-addr"], + "pageIndex": 0, + "pageSize": 1000, + "fullTx": True, + "txType": "ALL", + "order": "ASC" + }], + endpoint=endpoints[initial_funding[0]["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for stx in response["staking_transactions"]: + if stx["hash"] == s0_validator["hash"]: + assert stx["type"] == "CreateValidator" + assert_valid_json_structure(reference_create_validator_msg, stx["msg"]) diff --git a/tests/rpc_tests/test_transaction.py b/tests/rpc_tests/test_transaction.py new file mode 100644 index 0000000000..1cf265969b --- /dev/null +++ b/tests/rpc_tests/test_transaction.py @@ -0,0 +1,788 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Tests here are related to sending a plain transaction & require a +feedback loop with the chain. + +TODO: negative test cases + +As with all tests, there are 2 JSON-RPC versions/namespaces (v1 & v2) where their difference +is only suppose to be in the types of their params & returns. v1 keeps everything in hex and +v2 uses decimal when possible. However, there are some (legacy) discrepancies that some tests +enforce. These tests are noted and should NOT be broken. +""" +import json +import time + +import pytest +from flaky import flaky +from pyhmy import ( + account, + blockchain, +) +from pyhmy.rpc.request import ( + base_request +) + +import txs +from txs import ( + tx_timeout, + endpoints, + initial_funding, + get_transaction, + send_and_confirm_transaction, + send_transaction +) +from utils import ( + check_and_unpack_rpc_response, + assert_valid_json_structure, + mutually_exclusive_test, + rerun_delay_filter +) + + +_mutex_scope = "transaction" + + +@pytest.fixture(scope="module") +@txs.cross_shard +def cross_shard_txs(): + """ + Fixture for 2 cross shard transaction. + + Returned tuple has cx from s0 -> s1 as element 0, cx from s1 -> s0 as element 1. + """ + s0_test_tx = { + "from": "one1ue25q6jk0xk3dth4pxur9e742vcqfwulhwqh45", + "to": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", + # erupt concert hat tree anger discover disease town gasp lemon gesture fiber spread season mixture host awake tennis issue orbit member film winter glass + "amount": "1000", + "from-shard": 0, + "to-shard": 1, + "hash": "0x9dae9c8e2c8abc8eebab1f7731f5c28cacf2ced913f4e4d49d000f74df0edca2", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac008252088001945d5f0e515d3714ff3118d1378dbb2f36f7face43893635c9adc5dea000008027a0a45a914e5072d383158f790c34019c2ea2e60a1826cf2c95fa758b8a7168e52fa04ee2ac08ae98d0c9644feffdbc9b036d2be617cb7f92104ca7274eb9f102c9a7", + } + s1_test_tx = { + "from": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", + "to": "one1qljfd3pnfjwr86ll6d0s6khcqhw8969p9l7fw3", + # faculty pave mad mind siren unfold invite avocado teach engine mimic mouse frown topple match thunder syrup fame material feed occur kit install clog + "amount": "500", + "from-shard": 1, + "to-shard": 0, + "hash": "0x30e6cb1f8889d115512b1b5963aaefa66e180f350ed78c504d24b7ea224ac123", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac0082520801809407e496c4334c9c33ebffd35f0d5af805dc72e8a1891b1ae4d6e2ef5000008027a093992f9dc99fa49f48afca645e41affa23efbdc2035da784524eda018fe3ead6a017471c901f17b9d467bf0a4ec1871870a6592d6e573148dd5091a8c979656ad3", + } + txs = [None, None] # s0 -> s1 is element 0, s1 -> s0 is element 1 + + in_initially_funded = False + for tx in initial_funding: + if tx["to"] == s0_test_tx["from"] and tx["to-shard"] == s0_test_tx["from-shard"]: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test transaction from address {s0_test_tx['from']} " + f"not found in set of initially funded accounts.") + + tx_response = get_transaction(s0_test_tx["hash"], s0_test_tx["from-shard"]) + txs[0] = send_and_confirm_transaction(s0_test_tx) if tx_response is None else tx_response + start_time = time.time() + while time.time() - start_time < tx_timeout: + tx_response = get_transaction(s1_test_tx["hash"], s1_test_tx["from-shard"]) + if tx_response is not None: + txs[1] = tx_response + return tuple(txs) + elif account.get_balance(s1_test_tx["from"], endpoint=endpoints[s1_test_tx["from-shard"]]) >= 1e18: + txs[1] = send_and_confirm_transaction(s1_test_tx) + return tuple(txs) + raise AssertionError(f"Could not confirm cross shard transaction on 'to-shard' " + f"(balance not updated) for tx: {json.dumps(s0_test_tx, indent=2)}") + + +def test_get_pool_stats(): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = { + "executable-count": 0, + "non-executable-count": 0 + } + + raw_response = base_request("hmy_getPoolStats", params=[], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + raw_response = base_request("hmyv2_getPoolStats", params=[], endpoint=endpoints[0]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +def test_get_current_transaction_error_sink(): + """ + Note that v1 & v2 have the same responses. + """ + error_tx = { + "from": "one1ujsjs4mhds75xnws0yx0v8l2rvyp67arwzqrvz", + "to": "one1wfn43ynxhhdrrjnddqcr74u38frqc7hqjhhdkx", + # odor middle lake course smooth drive tone oven stone canyon chapter special recall page tomorrow north moon impose original under shaft guess popular debate + "amount": "1000000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x2f3be62d06027ec35369680329b2796cd811a902f2fe5cd67d761e962a3639a4", + "nonce": "0x0", + "signed-raw-tx": "0xf870808506fc23ac008252088080947267589266bdda31ca6d68303f57913a460c7ae08ad3c21bcecceda10000008028a06fb1e5a03bf27f68d48b79cb12dfefcdefcaa72113f80bf3a9ccc7f4614bcfa3a018ba6c8c1e7bba73352ba966b28e5327ba253f70bc6032cab2d5a0ce12f3bd6f", + } + reference_response = [ + { + "tx-hash-id": "0x371a399f7f62a5f372d3388a07250e16ee56ac763bd3a0c8c5f628f1e1975679", + "time-at-rejection": 1594797464, + "error-message": "transaction gas-price is 0.000000000000000000 ONE: transaction underpriced" + } + ] + + response = base_request('hmy_sendRawTransaction', params=[error_tx["signed-raw-tx"]], + endpoint=endpoints[error_tx["from-shard"]]) + check_and_unpack_rpc_response(response, expect_error=True) # Send invalid transaction directly... + + # Check v1 + raw_response = base_request("hmy_getCurrentTransactionErrorSink", params=[], + endpoint=endpoints[error_tx["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + found_errored_tx = False + for err in response: + if err["tx-hash-id"] == error_tx["hash"]: + found_errored_tx = True + break + assert found_errored_tx, f"Could not find errored transaction (hash {error_tx['hash']}) in {json.dumps(response, indent=2)}" + + # Check v2 + raw_response = base_request("hmyv2_getCurrentTransactionErrorSink", params=[], + endpoint=endpoints[error_tx["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + found_errored_tx = False + for err in response: + if err["tx-hash-id"] == error_tx["hash"]: + found_errored_tx = True + break + assert found_errored_tx, f"Could not find errored transaction (hash {error_tx['hash']}) in {json.dumps(response, indent=2)}" + + +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@mutually_exclusive_test(scope=_mutex_scope) +@txs.cross_shard +def test_resend_cx(cross_shard_txs): + """ + Note that v1 & v2 have the same responses. + """ + reference_response = True + + for tx in cross_shard_txs: + raw_response = base_request("hmy_resendCx", params=[tx["hash"]], + endpoint=endpoints[tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + raw_response = base_request("hmyv2_resendCx", params=[tx["hash"]], + endpoint=endpoints[tx["shardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@txs.cross_shard +def test_get_pending_cx_receipts(): + """ + Note that v1 & v2 have the same responses. + """ + cx = { + "from": "one19l4hghvh40fyldxfznn0a3ss7d5gk0dmytdql4", + "to": "one1ds3fayprfl6j7yd6mpwfncj9c0ajmhvmvhnmpm", + # erupt concert hat tree anger discover disease town gasp lemon gesture fiber spread season mixture host awake tennis issue orbit member film winter glass + "amount": "1000", + "from-shard": 0, + "to-shard": 1, + "hash": "0x33e4c0a582f87731a474332ca712b20f322afd0221aa3f4a287c985afab52476", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac008252088001946c229e90234ff52f11bad85c99e245c3fb2ddd9b893635c9adc5dea000008027a0978e0924045ba31ea891da261895f3d2840e687f0fd5df35208df2358bac69e7a05d588e2d823b65773537337d434affd0374c1331cd96841ff1513ee55504a8d1", + } + reference_response = [ + { + "receipts": [ + { + "txHash": "0x819b0d7902134dadd07851edba0e8694e60c1aee057a96d2ceb4a9118cee0298", + "from": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", + "to": "one1qljfd3pnfjwr86ll6d0s6khcqhw8969p9l7fw3", + "shardID": 1, + "toShardID": 0, + "amount": 500000000000000000000 + } + ], + "merkleProof": { + "blockNum": 35, + "blockHash": "0xe07abb23824f658f452012f22e2d557a270c320058a39d6c6d5d2d53d1d7e427", + "shardID": 1, + "receiptHash": "0xb7f422b693a5cffd3d98b2fd4f9f833e10421bcd6d488e5cd8c2fcbcf1ecd13c", + "shardIDs": [ + 0 + ], + "shardHashes": [ + "0x31db710789deaa5a1721f7bf66d3eabddfbb9e712b5ba6cdc7b183f5d9dc9b51" + ] + }, + "header": { + "shardID": 1, + "hash": "0x2e0295f760bc69cdf840576636f61602f8b13ea5172562837c10a9b6f5fa711e", + "number": "0x23", + "viewID": 35, + "epoch": 5 + }, + "commitSig": "G7oQCfiRJjl8s1i7B2xxPWZefCW5muiqyNY0PwcNOFt2QQkRC95ongKIGuIKCLMAVkDpkZRdC7B0cUoe3tKceT6/9++sxcwPRQ2NBWA/u6Gkl6UneKs4Xzhpuez2MoOG", + "commitBitmap": "Pw==" + } + ] + + if get_transaction(cx["hash"], cx["from-shard"]) is not None: + pytest.skip(f"Test cross shard transaction (hash {cx['hash']}) already present on chain...") + + send_transaction(cx, confirm_submission=True) + + start_time = time.time() + v1_success, v2_success = False, False + while time.time() - start_time <= tx_timeout * 2: # Cross shards are generally slower... + if not v1_success: + raw_response = base_request("hmy_getPendingCXReceipts", endpoint=endpoints[cx["to-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for cx_receipt in response: + for r in cx_receipt["receipts"]: + if r["txHash"] == cx["hash"]: + v1_success = True + + if not v2_success: + raw_response = base_request("hmyv2_getPendingCXReceipts", endpoint=endpoints[cx["to-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for cx_receipt in response: + for r in cx_receipt["receipts"]: + if r["txHash"] == cx["hash"]: + v2_success = True + + time.sleep(0.5) + if v1_success and v2_success: + return + + raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(cx)}") + + +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@mutually_exclusive_test(scope=_mutex_scope) +@txs.cross_shard +def test_get_cx_receipt_by_hash_v1(cross_shard_txs): + reference_response = { + "blockHash": "0xf12f3aefd7f189286b6da30871a47946c11f9c1673b3b693f9d37d659f69e018", + "blockNumber": "0x21", + "hash": "0xc0a84ec15fc3391089f20fa6b9cc90c654eb8dd2f6815297de89eef38ce4fe2b", + "from": "one1ue25q6jk0xk3dth4pxur9e742vcqfwulhwqh45", + "to": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", + "shardID": 0, + "toShardID": 1, + "value": "0x3635c9adc5dea00000" + } + + raw_response = base_request("hmy_getCXReceiptByHash", params=[cross_shard_txs[0]["hash"]], + endpoint=endpoints[cross_shard_txs[0]["toShardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +@flaky(max_runs=6, rerun_filter=rerun_delay_filter(delay=8)) +@mutually_exclusive_test(scope=_mutex_scope) +@txs.cross_shard +def test_get_cx_receipt_by_hash_v2(cross_shard_txs): + reference_response = { + "blockHash": "0xf12f3aefd7f189286b6da30871a47946c11f9c1673b3b693f9d37d659f69e018", + "blockNumber": 33, + "hash": "0xc0a84ec15fc3391089f20fa6b9cc90c654eb8dd2f6815297de89eef38ce4fe2b", + "from": "one1ue25q6jk0xk3dth4pxur9e742vcqfwulhwqh45", + "to": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", + "shardID": 0, + "toShardID": 1, + "value": 1000000000000000000000 + } + + raw_response = base_request("hmyv2_getCXReceiptByHash", params=[cross_shard_txs[0]["hash"]], + endpoint=endpoints[cross_shard_txs[0]["toShardID"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + + +@pytest.mark.run(order=0) +def test_send_raw_transaction_v1(): + tx = { + "from": "one1pvkjamc0q96s6z62qzz6e09k2qrqqdj34ylxvd", + "to": "one1mjunf85vnhc4drv57ugsyg2fxjnsq920qzkpwq", + # identify energy glimpse train script text town amused major slot armed fiction park alter dance live snow path picture desk metal voice distance good + "amount": "1000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x5e1ecefd00a7ce07ad1b307ac6da86544c68815eed4b5c605f151e538d2b416c", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac00825208808094dcb9349e8c9df1568d94f71102214934a700154f893635c9adc5dea000008028a0c4214018d34fe9d2021c9bdc9a05247de4d55a304ef4d5a7c5fefea629008697a03edf9fc15552602015dbd1091dd71db17efb0a52d664aeb639cb373dbe20e81f", + } + reference_response = { + "code": -32000, + "message": "transaction already finalized" + } + + if get_transaction(tx["hash"], tx["from-shard"]) is not None: + pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") + + # Submit new transaction... + response = base_request('hmy_sendRawTransaction', params=[tx["signed-raw-tx"]], + endpoint=endpoints[tx["from-shard"]]) + tx_hash = check_and_unpack_rpc_response(response, expect_error=False) + assert tx_hash == tx["hash"], f"Expect submitted transaction to get tx hash of {tx['hash']}, got {tx_hash}" + + # Test finalized transaction error... + start_time = time.time() + while time.time() - start_time <= tx_timeout: + if get_transaction(tx["hash"], tx["from-shard"]) is not None: + raw_response = base_request('hmy_sendRawTransaction', params=[tx["signed-raw-tx"]], + endpoint=endpoints[tx["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=True) + assert_valid_json_structure(reference_response, response) + assert reference_response["code"] == response["code"], f"Expected error code {reference_response['code']}, " \ + f"got {response['code']}" + return + time.sleep(0.25) + raise AssertionError(f"Timeout! Finalized transaction not found for {json.dumps(tx, indent=2)}") + + +@pytest.mark.run(order=0) +def test_send_raw_transaction_v2(): + tx = { + "from": "one13lu674f3jkfk2qhsngfc2vhcf372wprctdjvgu", + "to": "one14jeshxg75gdr5dz8sg7fm2sjvw7snnsdw98f0y", + # humor brain crouch walk focus slush material sort used refuse exist prefer obscure above grow maze scheme myself liquid lab fresh awful easily debris + "amount": "1000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x73e2aa48841b6d87eb6d7a4f6fc0e4253e1c806fdacd420b4d100f718e9dcd62", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac00825208808094acb30b991ea21a3a3447823c9daa1263bd09ce0d893635c9adc5dea000008028a02607a24abff19534b98b0a6e365ff56f7db2449e793ce6e241263154b7527d81a02db39163c82772ab5b5276f096a39ab0ed5608f187e0b3be0273024a98c5a205", + } + reference_response = { + "code": -32000, + "message": "transaction already finalized" + } + + if get_transaction(tx["hash"], tx["from-shard"]) is not None: + pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") + + # Submit new transaction... + response = base_request('hmyv2_sendRawTransaction', params=[tx["signed-raw-tx"]], + endpoint=endpoints[tx["from-shard"]]) + tx_hash = check_and_unpack_rpc_response(response, expect_error=False) + assert tx_hash == tx["hash"], f"Expect submitted transaction to get tx hash of {tx['hash']}, got {tx_hash}" + + # Test finalized transaction error... + start_time = time.time() + while time.time() - start_time <= tx_timeout: + if get_transaction(tx["hash"], tx["from-shard"]) is not None: + raw_response = base_request('hmyv2_sendRawTransaction', params=[tx["signed-raw-tx"]], + endpoint=endpoints[tx["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=True) + assert_valid_json_structure(reference_response, response) + assert reference_response["code"] == response["code"], f"Expected error code {reference_response['code']}, " \ + f"got {response['code']}" + return + time.sleep(0.25) + raise AssertionError(f"Timeout! Finalized transaction not found for {json.dumps(tx, indent=2)}") + + +@pytest.mark.run(order=0) +def test_get_transaction_by_hash_v1(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": "0x4", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": "0x5f0ec12e", + "gas": "0x5208", + "gasPrice": "0x6fc23ac00", + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "input": "0x", + "nonce": "0x0", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": "0x0", + "value": "0x152d02c7e14af6800000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + init_tx_record = initial_funding[0] + + raw_response = base_request("hmy_getTransactionByHash", + params=[init_tx_record["hash"]], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['hash']}" + + +@pytest.mark.run(order=0) +def test_get_transaction_by_hash_v2(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": 4, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": 1594802478, + "gas": 21000, + "gasPrice": 30000000000, + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "input": "0x", + "nonce": 0, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": 0, + "value": 100000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + init_tx_record = initial_funding[0] + + raw_response = base_request("hmyv2_getTransactionByHash", + params=[init_tx_record["hash"]], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['hash']}" + + +@pytest.mark.run(order=0) +def test_get_transaction_receipt_v1(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": "0x4", + "contractAddress": None, + "cumulativeGasUsed": "0x5208", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "gasUsed": "0x5208", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "shardID": 0, + "status": "0x1", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionHash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "transactionIndex": "0x0" + } + init_tx_record = initial_funding[0] + + raw_response = base_request("hmy_getTransactionReceipt", + params=[init_tx_record["hash"]], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["transactionHash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['transactionHash']}" + + +@pytest.mark.run(order=0) +def test_get_transaction_receipt_v2(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": 4, + "contractAddress": None, + "cumulativeGasUsed": 21000, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "gasUsed": 21000, + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "shardID": 0, + "status": 1, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionHash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "transactionIndex": 0 + } + init_tx_record = initial_funding[0] + + raw_response = base_request("hmyv2_getTransactionReceipt", + params=[init_tx_record["hash"]], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["transactionHash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['transactionHash']}" + + +def test_pending_transactions_v1(): + tx = { + "from": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", + "to": "one13awvzpjt7n3hcrmxax3elps7a6vw46u63kc28p", + # month liar edit pull vague intact entire slab satoshi angle core unlock useless wrestle kite merry sure quiz day frame update recycle fault lecture + "amount": "1000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x59272596c3633c486828755f8c56c379392d51eb5dd96f7c5b6a0805ff39c704", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac008252088080948f5cc1064bf4e37c0f66e9a39f861eee98eaeb9a893635c9adc5dea000008028a044385f2ccbc98d0ff8dfb4e5109334aed1e1d2e6aca327e07afc18d33e9cc236a060aa69ecddc755ed3ecf1cb2d59819b1d546241b448b71f64c4e32236d36c1cd", + } + reference_response = [ + { + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": None, + "from": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", + "timestamp": "0x0", + "gas": "0x5208", + "gasPrice": "0x6fc23ac00", + "hash": "0x59272596c3633c486828755f8c56c379392d51eb5dd96f7c5b6a0805ff39c704", + "input": "0x", + "nonce": "0x0", + "to": "one13awvzpjt7n3hcrmxax3elps7a6vw46u63kc28p", + "transactionIndex": "0x0", + "value": "0x3635c9adc5dea00000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0xe876d901525a8799a8eb3ea03e2c1a43129c2ff3136ec10f6345f2899bab5026", + "s": "0x5c4f1e659b9d371c2e9994aee240b966e36b6dd609747d42c9d9c9f23371d808" + } + ] + + in_initially_funded = False + for init_tx in initial_funding: + if init_tx["to"] == tx["from"] and init_tx["to-shard"] == tx["from-shard"]: + in_initially_funded = True + break + if not in_initially_funded: + raise AssertionError(f"Test transaction from address {tx['from']} " + f"not found in set of initially funded accounts.") + + if get_transaction(tx["hash"], tx["from-shard"]) is not None: + pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") + + send_transaction(tx, confirm_submission=True) + + start_time = time.time() + while time.time() - start_time <= tx_timeout: + raw_response = base_request("hmy_pendingTransactions", endpoint=endpoints[tx["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for pending_tx in response: + if pending_tx["hash"] == tx["hash"]: + assert pending_tx["shardID"] == tx["from-shard"], f"Pending tx has from shard {pending_tx['shardID']}, " \ + f"expected shard {tx['from-shard']}" + assert pending_tx["toShardID"] == tx["to-shard"], f"Pending tx has to shard {pending_tx['toShardID']}, " \ + f"expected shard {tx['to-shard']}" + return + + raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(tx, indent=2)}") + + +def test_pending_transactions_v2(): + tx = { + "from": "one1u57rlv5q82deja6ew2l9hdy7ag3dwnw57x8s9t", + "to": "one1zchjhmsxksamlxuv7h3k9h5aeury670n2jck2u", + # kit attack eternal net bronze grace apple evil market spin evil tragic kid capital noble future shrimp gossip flee wonder album ahead catalog crawl + "amount": "1000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x82fd4678de1df49eb8dc4ca361300c950712bd7f328990e10ff6c252a86050b6", + "nonce": "0x0", + "signed-raw-tx": "0xf86f808506fc23ac00825208808094162f2bee06b43bbf9b8cf5e362de9dcf064d79f3893635c9adc5dea000008028a07a3dd13017fe6468b087fd3aec0cb2b6896fb4f78e3aa985172c39b3cd9db27aa068e6a91e4918342ee725d9e1cc29f6849b690df04bfde13145c8dd65f475b1f0", + } + reference_response = [ + { + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": None, + "from": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", + "timestamp": 0, + "gas": 21000, + "gasPrice": 30000000000, + "hash": "0x82fd4678de1df49eb8dc4ca361300c950712bd7f328990e10ff6c252a86050b6", + "input": "0x", + "nonce": 0, + "to": "one13awvzpjt7n3hcrmxax3elps7a6vw46u63kc28p", + "transactionIndex": 0, + "value": 1000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0xe876d901525a8799a8eb3ea03e2c1a43129c2ff3136ec10f6345f2899bab5026", + "s": "0x5c4f1e659b9d371c2e9994aee240b966e36b6dd609747d42c9d9c9f23371d808" + } + ] + + if get_transaction(tx["hash"], tx["from-shard"]) is not None: + pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") + + send_transaction(tx, confirm_submission=True) + + start_time = time.time() + while time.time() - start_time <= tx_timeout: + raw_response = base_request("hmyv2_pendingTransactions", endpoint=endpoints[tx["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + for pending_tx in response: + if pending_tx["hash"] == tx["hash"]: + assert pending_tx["shardID"] == tx["from-shard"], f"Pending tx has from shard {pending_tx['shardID']}, " \ + f"expected shard {tx['from-shard']}" + assert pending_tx["toShardID"] == tx["to-shard"], f"Pending tx has to shard {pending_tx['toShardID']}, " \ + f"expected shard {tx['to-shard']}" + return + + raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(tx, indent=2)}") + + +@pytest.mark.run(order=1) +def test_get_transaction_by_block_hash_and_index_v1(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": "0x4", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": "0x5f0ec12e", + "gas": "0x5208", + "gasPrice": "0x6fc23ac00", + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "input": "0x", + "nonce": "0x0", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": "0x0", + "value": "0x152d02c7e14af6800000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + + init_tx_record = initial_funding[0] + tx = get_transaction(init_tx_record["hash"], init_tx_record["from-shard"]) + blk = blockchain.get_block_by_hash(tx["blockHash"], endpoint=endpoints[tx["shardID"]], include_full_tx=False) + index, blk_hash = blk["transactions"].index(init_tx_record["hash"]), tx["blockHash"] + + raw_response = base_request("hmy_getTransactionByBlockHashAndIndex", + params=[blk_hash, hex(index)], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['hash']}" + + +@pytest.mark.run(order=1) +def test_get_transaction_by_block_hash_and_index_v2(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": 4, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": 1594802478, + "gas": 21000, + "gasPrice": 30000000000, + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "input": "0x", + "nonce": 0, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": 0, + "value": 100000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + + init_tx_record = initial_funding[0] + tx = get_transaction(init_tx_record["hash"], init_tx_record["from-shard"]) + blk = blockchain.get_block_by_hash(tx["blockHash"], endpoint=endpoints[tx["shardID"]], include_full_tx=False) + index, blk_hash = blk["transactions"].index(init_tx_record["hash"]), tx["blockHash"] + + raw_response = base_request("hmyv2_getTransactionByBlockHashAndIndex", + params=[blk_hash, index], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['hash']}" + + +@pytest.mark.run(order=1) +def test_get_transaction_by_block_number_and_index_v1(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": "0x4", + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": "0x5f0ec12e", + "gas": "0x5208", + "gasPrice": "0x6fc23ac00", + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "input": "0x", + "nonce": "0x0", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": "0x0", + "value": "0x152d02c7e14af6800000", + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + + init_tx_record = initial_funding[0] + tx = get_transaction(init_tx_record["hash"], init_tx_record["from-shard"]) + blk = blockchain.get_block_by_hash(tx["blockHash"], endpoint=endpoints[tx["shardID"]], include_full_tx=False) + index, blk_num = blk["transactions"].index(init_tx_record["hash"]), tx["blockNumber"] + + raw_response = base_request("hmy_getTransactionByBlockNumberAndIndex", + params=[blk_num, hex(index)], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['hash']}" + + +@pytest.mark.run(order=1) +def test_get_transaction_by_block_number_and_index_v2(): + reference_response = { + "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", + "blockNumber": 4, + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "timestamp": 1594802478, + "gas": 21000, + "gasPrice": 30000000000, + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "input": "0x", + "nonce": 0, + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + "transactionIndex": 0, + "value": 100000000000000000000000, + "shardID": 0, + "toShardID": 0, + "v": "0x28", + "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", + "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" + } + + init_tx_record = initial_funding[0] + tx = get_transaction(init_tx_record["hash"], init_tx_record["from-shard"]) + blk = blockchain.get_block_by_hash(tx["blockHash"], endpoint=endpoints[tx["shardID"]], include_full_tx=False) + index, blk_num = blk["transactions"].index(init_tx_record["hash"]), tx["blockNumber"] + + raw_response = base_request("hmyv2_getTransactionByBlockNumberAndIndex", + params=[int(blk_num, 16), index], + endpoint=endpoints[init_tx_record["from-shard"]]) + response = check_and_unpack_rpc_response(raw_response, expect_error=False) + assert_valid_json_structure(reference_response, response) + assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ + f"got {response['hash']}" diff --git a/tests/rpc_tests/txs.py b/tests/rpc_tests/txs.py new file mode 100644 index 0000000000..2b6b8cac17 --- /dev/null +++ b/tests/rpc_tests/txs.py @@ -0,0 +1,404 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Stores all the transaction information used in the test suite. + +INVARIANT: Each account only sends 1 plain transaction (per shard) except for initial transaction(s). +""" +import functools +import json +import time +import random + +from pyhmy import ( + account, + blockchain +) +from pyhmy.rpc.request import ( + base_request +) + +from utils import ( + check_and_unpack_rpc_response, + is_valid_json_rpc +) + +tx_timeout = 50 # In seconds +beacon_shard_id = 0 +_is_cross_shard_era = False +_is_staking_era = False + +# Endpoints sorted by shard +endpoints = [ + "http://localhost:9598/", # shard 0 + "http://localhost:9596/", # shard 1 +] + +# ORDER MATERS: tx n cannot be sent without tx n-1 being sent first due to nonce +# Only exception on invariant. +initial_funding = [ + { + # Used by: `account_test_tx` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", + # scissors matter runway reduce flush illegal ancient absurd scare young copper ticket direct wise person hobby tomato chest edge cost wine crucial vendor elevator + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x4553da3a01770e4048862c39dd8f2996eacf990cf40932a358405239fe3650fc", + "nonce": "0x0", + "signed-raw-tx": "0xf870808506fc23ac0082520880809461544ab146a815e6088d49c40d285c2a1f2fe84f8a152d02c7e14af68000008028a0dd11189f8c54cf363145d1c877b49748e4c98f5a799cb712b76adac3966651f0a05a764e87c0f056bace46d1f410bea6c9267dbfe713abaa4b3bd05389456dd3c0", + }, + { + # Used by: `cross_shard_txs` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1ue25q6jk0xk3dth4pxur9e742vcqfwulhwqh45", + # obey scissors fiscal hood chaos grit all piano armed change general attract balcony hair cat outside hour quiz unhappy tattoo awful offer toddler invest + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x5dbef17541f1c375c692104419821aefeba47e62b1a28044abfef7f4a467cdd4", + "nonce": "0x1", + "signed-raw-tx": "0xf870018506fc23ac00825208808094e655406a5679ad16aef509b832e7d5533004bb9f8a152d02c7e14af68000008027a0298a98ab57c51f5544632f283e452d1158b4565c6d3cd8ad667ec6ea6a4de0b7a046ea90929a047862deda016845bce6711e8e82f59133230fa511024283b74916", + }, + { + # Used by: `test_get_pending_cx_receipts` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one19l4hghvh40fyldxfznn0a3ss7d5gk0dmytdql4", + # judge damage safe field faculty piece salon gentle riot unfair symptom sun exclude agree fantasy fossil catalog tool bounce tomorrow churn join very number + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x3d93962349fcd0e57fdfd17e94550dbd15ba75e8f2c1151a41b5535936e49abb", + "nonce": "0x2", + "signed-raw-tx": "0xf870028506fc23ac008252088080942feb745d97abd24fb4c914e6fec610f3688b3dbb8a152d02c7e14af68000008028a0084e402becab9df1ad57a8ff508dc6b64601839d385d6993ebc92e06f364184fa01500d6dbb3add350b89ff3957869af85eafa3bf29527b31f5ebe82db601c2d7e", + }, + { + # Used by: `test_pending_transactions_v1` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", + # science swim absent horse gas wink switch section soup pair chuckle rug paddle lottery message veteran poverty alone current prize spoil dune super crumble + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x6e5125487d2b41024aa8d8e9b37a85e1f8acb48aa422cc849477cbc3142db2ff", + "nonce": "0x3", + "signed-raw-tx": "0xf870038506fc23ac008252088080945bae24e14e1d654b77c88143bffc331b49d85b1f8a152d02c7e14af68000008028a0d665a57bb8783ac9830b870726315e49faea916aa1ca66b4725db8fef6c06592a077717c9ecad6270917f90513b4673815cc6e84774f04adac84369d7821658e3b", + }, + { + # Used by: `test_pending_transactions_v2` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1u57rlv5q82deja6ew2l9hdy7ag3dwnw57x8s9t", + # noble must all evoke core grass goose describe latin left because awful gossip tuna broccoli tomorrow piece enable theme comic below avoid dove high + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x7b5f795ca3ffbc05c6b79b52158f1dfafe8821e2f30f4a1939f22d6e347aadbb", + "nonce": "0x4", + "signed-raw-tx": "0xf870048506fc23ac00825208808094e53c3fb2803a9b99775972be5bb49eea22d74dd48a152d02c7e14af68000008027a044e33249ea5bcce6ac423bde73b78460df1cd91a1ce23c3396a987430edaa09fa0527b2650234543300d71190516481331a7a07c31fdebf039e4c439d145671cf2", + }, + { + # Used by: `test_send_raw_transaction_v1` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1pvkjamc0q96s6z62qzz6e09k2qrqqdj34ylxvd", + # satisfy spend chaos twice sort obvious mercy prize slow divert addict section love inflict claim turn elbow pet flock cigar social spoil turn ensure + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x7ed85da44ed014ea73f1196985643b92ce2577488a5910a92e209c543ead82f8", + "nonce": "0x5", + "signed-raw-tx": "0xf870058506fc23ac008252088080940b2d2eef0f01750d0b4a0085acbcb650060036518a152d02c7e14af68000008027a055c5b550d01e0ce9ba338f8d9cf190dd813ac7a8184e332e10eb1ffce8973243a030bf6f289ba3fa13415d0bd601abdb94630986efb59f9ce19d6c0a1e49d11502", + }, + { + # Used by: `test_send_raw_transaction_v2` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one13lu674f3jkfk2qhsngfc2vhcf372wprctdjvgu", + # organ truly miss sell visual pulse maid element slab sugar bullet absorb digital space dance long another man cherry fruit effort pluck august flag + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0xeaaedd017b3e2efedbe7d05f38a9ee5d7950547f73c997b08e5b2e6a694b1285", + "nonce": "0x6", + "signed-raw-tx": "0xf870068506fc23ac008252088080948ff9af553195936502f09a138532f84c7ca704788a152d02c7e14af68000008028a068a8211bdb8ae6ea7f85f140b37cfaa4e0a76e634bee673ac6e35d91b66700bea0795136404d542a1e40d16a924caaf1faee6243736b21f1ea7b4e3d6fb350f472", + }, + { + # Used by: `test_get_current_transaction_error_sink` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1ujsjs4mhds75xnws0yx0v8l2rvyp67arwzqrvz", + # video mind cash involve kitten mobile multiply shine foam citizen minimum busy slab keen under food swamp fortune dumb slice beyond piano forest call + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x242ffd4bfbd34857dc36c59b7370bd9b50d7aef07a29555bc99483ac7feb378d", + "nonce": "0x7", + "signed-raw-tx": "0xf870078506fc23ac00825208808094e4a12857776c3d434dd0790cf61fea1b081d7ba38a152d02c7e14af68000008028a0f09f48a6b86b0966de74f5ac242ab727332d9fad99ef0403fb22547770c3f3e5a078885614410f66af51b306090cfce7deeed59363dd40f758b5592e6a74f642a1", + }, + { + # Used by: `deployed_contract` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one156wkx832t0nxnaq6hxawy4c3udmnpzzddds60a", + # dove turkey fitness brush drip page senior lemon other climb govern fantasy entry reflect when biology hunt victory turkey volcano casino movie shed valve + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x078fa8486683e5c04e820dde99c8280af0848788df313ee20cc1e474bdcac821", + "nonce": "0x8", + "signed-raw-tx": "0xf870088506fc23ac00825208808094a69d631e2a5be669f41ab9bae25711e37730884d8a152d02c7e14af68000008027a01af975303e964b88bf2158a8fdc00fee0244322a301d33ef3117798979f9c255a01a14d5aff8b9e2f4eaff1ee3761467e35e55ab10993118ab6454a8b1235be413", + }, + { + # Used by: `s0_validator` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one109r0tns7av5sjew7a7fkekg4fs3pw0h76pp45e", + # proud guide else desk renew leave fix post fat angle throw gain field approve year umbrella era axis horn unlock trip guide replace accident + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x4a069bf42191da42f2955f045e4c304904073476c7bf8f7d1cf6bf7b9a2eb995", + "nonce": "0x9", + "signed-raw-tx": "0xf870098506fc23ac008252088080947946f5ce1eeb290965deef936cd9154c22173efe8a152d02c7e14af68000008028a0aa679ee9c7bc4741d55c9724f248f23d0a5a79c9f5bf960c6a07a3436d1234f4a063771c21dab504eb15f44efcfa97090ba072171e71b6df77a35ea84bc2b2302f", + }, + { + # Used by: `s1_validator` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1nmy8quw0924fss4r9km640pldzqegjk4wv4wts", + # aisle aware spatial sausage vibrant tennis useful admit junior light calm wear caution snack seven spoon yellow crater giraffe mirror spare educate result album + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x3ddcd1524386b985ed6ec4f0e02e6fcc4ad5180d1fffaa847c7ff95fd0c82029", + "nonce": "0xa", + "signed-raw-tx": "0xf8700a8506fc23ac008252088080949ec87071cf2aaa9842a32db7aabc3f6881944ad58a152d02c7e14af68000008027a075ffd26368005e0140659406472e875e22f3cef76f715a2e61d8fe3fd06de5d0a0407b1e42f8c876021a686399dcb1ac10baea0c87bd341463e95e8625cab559a9", + }, + { + # Used by: `test_delegation` & `test_undelegation` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one1v895jcvudcktswcmg2sldvmxvtvvdj2wuxj3hx", + # web topple now acid repeat inspire tomato inside nominee reflect latin salmon garbage negative liberty win royal faith hammer lawsuit west toddler payment coffee + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x48e942756c73070587af4d0b5191ca0b75438ea11da0157f950777cc1c711e03", + "nonce": "0xb", + "signed-raw-tx": "0xf8700b8506fc23ac0082520880809461cb49619c6e2cb83b1b42a1f6b36662d8c6c94e8a152d02c7e14af68000008027a031b487574472555b53591ee048d6036cf0cce14ebff7d5d1376371b337024d61a04dcc0298761d73c93a655954897b59e2ce2e78c35859c4fe24abdb6304ddf83a", + }, + { + # Used by: `test_pending_staking_transactions_v1` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one13v9m45m6yk9qmmcgyq603ucy0wdw9lfsxzsj9d", + # grief comfort prefer wealth foam consider kingdom secret comfort brush kit cereal hello ripple choose follow mammal swap city pistol drip unfair glass jacket + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x789a25e28c73dafcc5105205a629c297730d4da2cf95a5437d349d72d036d1e5", + "nonce": "0xc", + "signed-raw-tx": "0xf8700c8506fc23ac008252088080948b0bbad37a258a0def082034f8f3047b9ae2fd308a152d02c7e14af68000008027a04d8d18da12f99299421a10dd5b610e6fbd1247f5f3e5f20f0778ac1fde664f02a05835c5ca12d0629553783356663617de7686b11e3614bf117d308213149c5b31", + }, + { + # Used by: `test_pending_staking_transactions_v2` + "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", + "to": "one13muqj27fcd59gfrv7wzvuaupgkkwvwzlxun0ce", + # suit gate simple ship chicken labor twenty attend knee click quit emerge minimum veteran need group verify dish baby argue guard win tip swear + "amount": "100000", + "from-shard": 0, + "to-shard": 0, + "hash": "0x9971b136f9678f456e97ce0db8d912208b7d811f3b76a5cc52c88d444f005ff6", + "nonce": "0xd", + "signed-raw-tx": "0xf8700d8506fc23ac008252088080948ef8092bc9c36854246cf384ce778145ace6385f8a152d02c7e14af68000008028a062b0acdaebb337d29b2fea7fdc6da31a13011c011405a975aa1220c84757635ea03e1ea73564a792ce05717ac783bbb9fc593e077b8e6bbe8e82b661817dd3e99d", + }, +] + + +def is_cross_shard_era(): + """ + Returns if the network is in cross shard tx era... + """ + global _is_cross_shard_era + if _is_cross_shard_era: + return True + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + if all(blockchain.get_current_epoch(e) >= 1 for e in endpoints): + _is_cross_shard_era = True + return True + return False + + +def cross_shard(fn): + """ + Decorator for tests that requires a cross shard transaction + """ + + @functools.wraps(fn) + def wrap(*args, **kwargs): + while not is_cross_shard_era(): + pass + return fn(*args, **kwargs) + + return wrap + + +def is_staking_era(): + """ + Returns if the network is in staking era... + """ + global _is_staking_era + if _is_staking_era: + return True + time.sleep(random.uniform(0.5, 1.5)) # Random to stop burst spam of RPC calls. + threshold_epoch = blockchain.get_prestaking_epoch(endpoints[beacon_shard_id]) + if all(blockchain.get_current_epoch(e) >= threshold_epoch for e in endpoints): + _is_staking_era = True + return False + + +def staking(fn): + """ + Decorator for tests that requires staking epoch + """ + + @functools.wraps(fn) + def wrap(*args, **kwargs): + while not is_staking_era(): + pass + return fn(*args, **kwargs) + + return wrap + + +def send_transaction(tx_data, confirm_submission=False): + """ + Send the given transaction (`tx_data`), and check that it got submitted + to tx pool if `confirm_submission` is enabled. + + Node that tx_data follow the format of one of the entries in `initial_funding` + """ + assert isinstance(tx_data, dict), f"Sanity check: expected tx_data to be of type dict not {type(tx_data)}" + for el in ["from", "from-shard", "signed-raw-tx", "hash"]: + assert el in tx_data.keys(), f"Expected {el} as a key in {json.dumps(tx_data, indent=2)}" + + # Validate tx sender + assert_valid_test_from_address(tx_data["from"], tx_data["from-shard"], is_staking=False) + + # Send tx + response = base_request('hmy_sendRawTransaction', params=[tx_data["signed-raw-tx"]], + endpoint=endpoints[tx_data["from-shard"]]) + if confirm_submission: + tx_hash = check_and_unpack_rpc_response(response, expect_error=False) + assert tx_hash == tx_data["hash"], f"Expected submitted transaction to get tx hash of {tx_data['hash']}, " \ + f"got {tx_hash}" + else: + assert is_valid_json_rpc(response), f"Invalid JSON response: {response}" + + +def send_staking_transaction(tx_data, confirm_submission=False): + """ + Send the given staking transaction (`tx_data`), and check that it got submitted + to tx pool if `confirm_submission` is enabled. + + Node that tx_data follow the format of one of the entries in `initial_funding` + """ + assert isinstance(tx_data, dict), f"Sanity check: expected tx_data to be of type dict not {type(tx_data)}" + for el in ["signed-raw-tx", "hash"]: + assert el in tx_data.keys(), f"Expected {el} as a key in {json.dumps(tx_data, indent=2)}" + + # Send tx + response = base_request('hmy_sendRawStakingTransaction', params=[tx_data["signed-raw-tx"]], + endpoint=endpoints[0]) + if confirm_submission: + tx_hash = check_and_unpack_rpc_response(response, expect_error=False) + assert tx_hash == tx_data["hash"], f"Expected submitted staking transaction to get tx hash " \ + f"of {tx_data['hash']}, got {tx_hash}" + else: + assert is_valid_json_rpc(response), f"Invalid JSON response: {response}" + + +def send_and_confirm_transaction(tx_data, timeout=tx_timeout): + """ + Send and confirm the given transaction (`tx_data`) within the given `timeout`. + + Node that tx_data follow the format of one of the entries in `initial_funding`. + + Note that errored tx submission will not return an error early, instead, failed transactions will be + caught by timeout. This is done because it is possible to submit the same transaction multiple times, + thus causing the RPC to return an error, causing unwanted errors in tests that are ran in parallel. + """ + assert isinstance(tx_data, dict), f"Sanity check: expected tx_data to be of type dict not {type(tx_data)}" + for el in ["from-shard", "hash"]: + assert el in tx_data.keys(), f"Expected {el} as a key in {json.dumps(tx_data, indent=2)}" + + send_transaction(tx_data, confirm_submission=False) + # Do not check for errors since resending initial txs is fine & failed txs will be caught in confirm timeout. + + # Confirm tx within timeout window + start_time = time.time() + while time.time() - start_time <= timeout: + tx_response = get_transaction(tx_data["hash"], tx_data["from-shard"]) + if tx_response is not None: + if tx_response['blockNumber'] is not None: + return tx_response + time.sleep(random.uniform(0.2, 0.5)) # Random to stop burst spam of RPC calls. + raise AssertionError("Could not confirm transactions on-chain.") + + +def send_and_confirm_staking_transaction(tx_data, timeout=tx_timeout * 2): + """ + Send and confirm the given staking transaction (`tx_data`) within the given `timeout`. + + Node that tx_data follow the format of one of the entries in `initial_funding`. + + Note that errored tx submission will not return an error early, instead, failed transactions will be + caught by timeout. This is done because it is possible to submit the same transaction multiple times, + thus causing the RPC to return an error, causing unwanted errors in tests that are ran in parallel. + """ + assert isinstance(tx_data, dict), f"Sanity check: expected tx_data to be of type dict not {type(tx_data)}" + for el in ["hash"]: + assert el in tx_data.keys(), f"Expected {el} as a key in {json.dumps(tx_data, indent=2)}" + + send_staking_transaction(tx_data, confirm_submission=False) + # Do not check for errors since resending initial txs is fine & failed txs will be caught in confirm timeout. + + # Confirm tx within timeout window + start_time = time.time() + while time.time() - start_time <= timeout: + tx_response = get_staking_transaction(tx_data["hash"]) + if tx_response is not None: + if tx_response['blockNumber'] is not None: + return tx_response + time.sleep(random.uniform(0.2, 0.5)) # Random to stop burst spam of RPC calls. + raise AssertionError("Could not confirm staking transaction on-chain.") + + +def get_transaction(tx_hash, shard): + """ + Fetch the transaction for the given hash on the given shard. + It also checks that the RPC response is valid. + """ + assert isinstance(tx_hash, str), f"Sanity check: expect tx hash to be of type str not {type(tx_hash)}" + assert isinstance(shard, int), f"Sanity check: expect shard to be of type int not {type(shard)}" + raw_response = base_request('hmy_getTransactionByHash', params=[tx_hash], endpoint=endpoints[shard]) + return check_and_unpack_rpc_response(raw_response, expect_error=False) + + +def get_staking_transaction(tx_hash): + """ + Fetch the staking transaction for the given hash on the given shard. + It also checks that the RPC response is valid. + """ + assert isinstance(tx_hash, str), f"Sanity check: expect tx hash to be of type str not {type(tx_hash)}" + raw_response = base_request('hmy_getStakingTransactionByHash', params=[tx_hash], endpoint=endpoints[0]) + return check_and_unpack_rpc_response(raw_response, expect_error=False) + + +def assert_valid_test_from_address(address, shard, is_staking=False): + """ + Asserts that the given address is a valid 'from' address for a test transaction. + + Note that this considers the invariant for transactions. + """ + assert isinstance(address, str), f"Sanity check: Expect address {address} as a string." + assert isinstance(shard, int), f"Sanity check: Expect shard {shard} as am int." + assert isinstance(is_staking, bool), f"Sanity check: Expect is_staking {is_staking} as a bool." + assert account.is_valid_address(address), f"{address} is an invalid ONE address" + if not account.get_balance(address, endpoint=endpoints[shard]) >= 1e18: + raise AssertionError(f"Account {address} does not have at least 1 ONE on shard {shard}") + if not is_staking and account.get_transaction_count(address, endpoint=endpoints[shard]) != 0: + raise AssertionError(f"Account {address} has already sent a transaction, breaking the txs invariant") diff --git a/tests/rpc_tests/utils.py b/tests/rpc_tests/utils.py new file mode 100644 index 0000000000..b0ba6aef06 --- /dev/null +++ b/tests/rpc_tests/utils.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Here are a collection of helper function, classes, and decorators used in all of the tests. + +TODO: make this a library. +""" +import functools +import json +import time +import random +from threading import Lock + +from pyhmy import ( + account +) + +_mutually_exclusive_locks = {} + + +def is_valid_json_rpc(response): + """ + Checks if the given `response` is a valid JSON RPC 2.0 response. + """ + try: + d = json.loads(response) + except json.JSONDecodeError: + return False + if "jsonrpc" not in d.keys(): + return False + if d["jsonrpc"] != "2.0": + return False + if 'result' in d.keys(): + if "id" not in d.keys(): + return False + return True + elif 'error' in d.keys(): + error = d['error'] + if not isinstance(error, dict): + return False + if "code" not in error.keys(): + return False + if not isinstance(error["code"], int): + return False + if "message" not in error.keys(): + return False + if not isinstance(error["message"], str): + return False + return True + else: + return False + + +def assert_no_null_in_list(lst): + assert isinstance(lst, list), f"Sanity check: expected lst to be of type list not {type(lst)}" + assert None not in lst, f"Expected no nulls in {lst}" + + +def assert_valid_json_structure(reference, candidate): + """ + Asserts that the given `candidate` dict (from JSON format) has the + same keys and values as the `reference` dict (from JSON format). + + Note that if there is a list, the OVERLAPPING elements that are + non-null/non-None are the ONLY elements checked. + """ + if reference is None or candidate is None: + return + assert type(reference) == type(candidate), f"Expected type {type(reference)} not {type(candidate)} in {candidate}" + if type(reference) == list and reference and candidate: # If no element in list to check, ignore... + for i in range(min(len(reference), len(candidate))): + assert_valid_json_structure(reference[i], candidate[i]) + elif type(reference) == dict: + for key in reference.keys(): + assert key in candidate.keys(), f"Expected key '{key}' in {json.dumps(candidate, indent=2)}" + assert_valid_json_structure(reference[key], candidate[key]) + elif type(reference) == str: + if reference.startswith("0x"): + assert candidate.startswith("0x"), f"Expected a hex string, reference: {reference}, got {candidate}" + if reference.startswith("one1") and account.is_valid_address(reference): + assert account.is_valid_address( + candidate), f"Expected a valid ONE address, reference: {reference}, got {candidate} " + + +def check_and_unpack_rpc_response(response, expect_error=False): + """ + Checks the given `response` to ensure its a valid JSON-RPC response, then returns + the 'usable' part of the response (`error` or `result` depending on given expectation). + """ + if not response: + raise AssertionError("No response...") + assert is_valid_json_rpc(response), f"Invalid JSON response: {response}" + response = json.loads(response) + if expect_error: + assert "error" in response.keys(), f"Expected error in RPC response: {json.dumps(response, indent=2)}" + return response["error"] + else: + assert "result" in response.keys(), f"Expected result in RPC response: {json.dumps(response, indent=2)}" + return response["result"] + + +def rerun_delay_filter(delay=5): + """ + A simple filter to rerun a test after a given delay + """ + + def wrap(err, *args): + time.sleep(delay) + return True + + return wrap + + +def mutually_exclusive_test(scope=""): + """ + Decorator for tests that cannot run in parallel together. + """ + if scope not in _mutually_exclusive_locks.keys(): + _mutually_exclusive_locks[scope] = Lock() + + def decorator(fn): + @functools.wraps(fn) + def wrap(*args, **kwargs): + _mutually_exclusive_locks[scope].acquire() + try: + return fn(*args, **kwargs) + finally: + time.sleep(random.uniform(0.5, 1)) # Random to stop burst spam of RPC calls. + _mutually_exclusive_locks[scope].release() + + return wrap + + return decorator diff --git a/tests/scripts/release_test.sh b/tests/scripts/release_test.sh new file mode 100644 index 0000000000..288f092273 --- /dev/null +++ b/tests/scripts/release_test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e + +for i in {1..10} +do + echo "=== START TEST NUMBER ${i} ===" + docker run -v "$(go env GOPATH)/src/github.com/harmony-one/harmony:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test + echo "=== END TEST NUMBER ${i} ===" +done diff --git a/tests/scripts/run.sh b/tests/scripts/run.sh new file mode 100644 index 0000000000..63a4167604 --- /dev/null +++ b/tests/scripts/run.sh @@ -0,0 +1,226 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +harmony_dir="$(go env GOPATH)/src/github.com/harmony-one/harmony" +localnet_config=$(realpath "$DIR/../configs/localnet_deploy.config") + +function stop() { + if [ "$KEEP" == "true" ]; then + tail -f /dev/null + fi + kill_localnet +} + +function kill_localnet() { + pushd "$(pwd)" + cd "$harmony_dir" && bash ./test/kill_node.sh + popd +} + +function setup() { + if [ ! -d "$harmony_dir" ]; then + echo "Test setup FAILED: Missing harmony directory at $harmony_dir" + exit 1 + fi + if [ ! -f "$localnet_config" ]; then + echo "Test setup FAILED: Missing localnet deploy config at $localnet_config" + exit 1 + fi + kill_localnet + error=0 # reset error/exit code +} + +function build_and_start_localnet() { + local localnet_log="$harmony_dir/localnet_deploy.log" + rm -rf "$harmony_dir/tmp_log*" + rm -rf "$harmony_dir/.dht*" + rm -f "$localnet_log" + rm -f "$harmony_dir/*.rlp" + pushd "$(pwd)" + cd "$harmony_dir" + if [ "$BUILD" == "true" ]; then + # Dynamic for faster build iterations + bash ./scripts/go_executable_build.sh -S + BUILD=False + fi + bash ./test/deploy.sh -e -B -D 60000 "$localnet_config" 2>&1 | tee "$localnet_log" + popd +} + +function go_tests() { + echo -e "\n=== \e[38;5;0;48;5;255mSTARTING GO TESTS\e[0m ===\n" + pushd "$(pwd)" + cd "$harmony_dir" + if [ "$BUILD" == "true" ]; then + # Dynamic for faster build iterations + bash ./scripts/go_executable_build.sh -S + BUILD=False + fi + bash ./scripts/travis_go_checker.sh || error=1 + echo -e "\n=== \e[38;5;0;48;5;255mFINISHED GO TESTS\e[0m ===\n" + if ((error == 1)); then + echo "FAILED GO TESTS" + else + echo "Passed GO tests" + fi + popd +} + +function rpc_tests() { + echo -e "\n=== \e[38;5;0;48;5;255mSTARTING RPC TESTS\e[0m ===\n" + build_and_start_localnet || exit 1 & + sleep 30 + # WARNING: Assumtion is that EPOCH 2 can process ALL test transaction types... + wait_for_epoch 2 300 # Timeout at ~900 seconds + + echo "Starting test suite..." + sleep 3 + # Use 4 or less threads, high thread count can lead to burst RPC calls, which can lead to some RPC calls being rejected. + cd "$DIR/../" && python3 -u -m py.test -v -r s -s rpc_tests -x || error=1 #-n 4 + echo -e "\n=== \e[38;5;0;48;5;255mFINISHED RPC TESTS\e[0m ===\n" + if ((error == 1)); then + echo "FAILED RPC TESTS" + else + echo "Passed RPC tests" + fi +} + +function rosetta_tests() { + echo -e "\n=== \e[38;5;0;48;5;255mSTARTING ROSETTA API TESTS\e[0m ===\n" + build_and_start_localnet || exit 1 & + sleep 30 + # WARNING: Assumtion is that EPOCH 2 can process ALL test transaction types... + wait_for_epoch 2 300 # Timeout at ~900 seconds + + echo "Starting Rosetta test suite, in quiet mode" + sleep 3 + # Run tests sequentially for clear error tracing + pwd + echo "dir: $DIR/../configs/localnet_rosetta_test_s0.json" + echo "[ROSETTA] check:construction s0" + rosetta-cli check:construction --configuration-file "$DIR/../configs/localnet_rosetta_test_s0.json" > /dev/null 2>1 || error=1 + echo "[ROSETTA] check:data s0" + rosetta-cli check:data --configuration-file "$DIR/../configs/localnet_rosetta_test_s0.json" > /dev/null 2>1 || error=1 + echo "[ROSETTA] check:construction s1" + rosetta-cli check:construction --configuration-file "$DIR/../configs/localnet_rosetta_test_s1.json" > /dev/null 2>1 || error=1 + echo "[ROSETTA] check:data s1" + rosetta-cli check:data --configuration-file "$DIR/../configs/localnet_rosetta_test_s1.json" > /dev/null 2>1 || error=1 + echo -e "\n=== \e[38;5;0;48;5;255mFINISHED ROSETTA API TESTS\e[0m ===\n" + if ((error == 1)); then + echo "FAILED ROSETTA TESTS" + else + echo "Passed rosetta tests" + fi +} + +function wait_for_localnet_boot() { + timeout=70 + if [ -n "$1" ]; then + timeout=$1 + fi + i=0 + until curl --silent --location --request POST "localhost:9500" \ + --header "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":1}' >/dev/null; do + echo "Trying to connect to localnet..." + if ((i > timeout)); then + echo "TIMEOUT REACHED" + exit 1 + fi + sleep 3 + i=$((i + 1)) + done + + valid=false + until $valid; do + result=$(curl --silent --location --request POST "localhost:9500" \ + --header "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"hmy_blockNumber","params":[],"id":1}' | jq -r '.result') + if ((result>0)); then + valid=true + else + echo "Waiting for localnet to boot..." + if ((i > timeout)); then + echo "TIMEOUT REACHED" + exit 1 + fi + sleep 3 + i=$((i + 1)) + fi + done + + sleep 15 # Give some slack to ensure localnet is booted... + echo "Localnet booted." +} + +function wait_for_epoch() { + wait_for_localnet_boot "$2" + cur_epoch=0 + echo "Waiting for epoch $1..." + until ((cur_epoch >= "$1")); do + cur_epoch=$(curl --silent --location --request POST "localhost:9500" \ + --header "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"hmyv2_latestHeader","params":[],"id":1}' | jq .result.epoch) + if ((i > timeout)); then + echo "TIMEOUT REACHED" + exit 1 + fi + sleep 3 + i=$((i + 1)) + done +} + +trap stop SIGINT SIGTERM EXIT + +BUILD=true +KEEP=false +GO=true +RPC=true +ROSETTA=true + +while getopts "Bkgnr" option; do + case ${option} in + B) BUILD=false ;; + k) KEEP=true ;; + g) RPC=false + ROSETTA=false + ;; + n) + GO=false + ROSETTA=false + ;; + r) + GO=false + RPC=false + ;; + *) echo " +Integration tester for localnet + +Option: Help: +-B Do NOT build binray before testing +-k Keep localnet running after Node API tests are finished +-g ONLY run go tests & checks +-n ONLY run the RPC tests +-r ONLY run the rosetta API tests +" + exit 0 + ;; + esac +done + +setup + +if [ "$GO" == "true" ]; then + go_tests +fi + +if [ "$RPC" == "true" ]; then + rpc_tests +fi + +if [ "$ROSETTA" == "true" ]; then + rosetta_tests +fi + +exit "$error" From f2be022b92fb5b04fbff8bb63dbec643188016f8 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:23:50 -0400 Subject: [PATCH 48/66] Test. --- .dockerignore | 17 +- Makefile | 2 +- Tests.Dockerfile | 68 ++ api/proto/message/client.go | 2 +- api/proto/message/gen.sh | 2 +- .../{message.pb.go => harmonymessage.pb.go} | 591 +++++++++--------- .../{message.proto => harmonymessage.proto} | 4 +- ...e_grpc.pb.go => harmonymessage_grpc.pb.go} | 10 +- api/proto/message/message.go | 2 +- api/proto/message/server.go | 2 +- cmd/bootnode/main.go | 2 +- cmd/harmony/main.go | 4 +- go.mod | 134 ++-- go.sum | 370 ++++++----- p2p/host.go | 15 +- scripts/travis_rpc_checker.sh | 9 +- tests/Dockerfile | 30 +- 17 files changed, 717 insertions(+), 547 deletions(-) create mode 100644 Tests.Dockerfile rename api/proto/message/{message.pb.go => harmonymessage.pb.go} (55%) rename api/proto/message/{message.proto => harmonymessage.proto} (98%) rename api/proto/message/{message_grpc.pb.go => harmonymessage_grpc.pb.go} (94%) diff --git a/.dockerignore b/.dockerignore index 28832631b0..b02b8065da 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,15 @@ -* -!scripts/docker +harmony_db* +bin +cache +.DS_Store +*.log +log-* +tmp_log +*.rlp +**/*.rlp +.hmykey +db-127.0.0.1-* +db* +.dht +.dht-* +explorer_storage_* diff --git a/Makefile b/Makefile index f6c39a66f2..93b7930c86 100644 --- a/Makefile +++ b/Makefile @@ -184,5 +184,5 @@ debug_external: clean build_localnet_validator: bash test/build-localnet-validator.sh -generate: +protofiles: bash ./scripts/gogenerate.sh diff --git a/Tests.Dockerfile b/Tests.Dockerfile new file mode 100644 index 0000000000..cb8a055eca --- /dev/null +++ b/Tests.Dockerfile @@ -0,0 +1,68 @@ +FROM golang:1.21 + +WORKDIR $GOPATH/src/github.com/harmony-one + +SHELL ["/bin/bash", "-c"] + +# These are split into multiple lines to allow debugging the error message that I cannot reproduce locally +# The command `xxx` returned a non-zero code: 100 +RUN apt clean > /dev/null 2>1 +RUN apt update > /dev/null 2>1 +RUN apt upgrade -y > /dev/null 2>1 +RUN apt update -y > /dev/null 2>1 +RUN apt install -y unzip libgmp-dev libssl-dev curl git jq make gcc g++ bash sudo python3 python3-pip + +#RUN #git clone https://github.com/harmony-one/harmony.git > /dev/null 2>1 \ +RUN git clone https://github.com/harmony-one/bls.git > /dev/null 2>1 +RUN git clone https://github.com/harmony-one/mcl.git > /dev/null 2>1 + +# Fix complaints about Docker / root / user ownership for Golang "VCS stamping" +# https://github.com/golang/go/blob/3900ba4baf0e3b309a55b5ac4dd25f709df09772/src/cmd/go/internal/vcs/vcs.go +RUN git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/harmony > /dev/null 2>1 \ + && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/bls > /dev/null 2>1 \ + && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/mcl > /dev/null 2>1 + +# Build to fetch all dependencies for faster test builds +WORKDIR $GOPATH/src/github.com/harmony-one/harmony +COPY . . +# Выполняем команду pwd для вывода текущего каталога +RUN echo "Current directory:" && pwd + +# Проверяем содержимое каталога +RUN echo "Listing directory contents:" && ls -la + +RUN go mod tidy +#RUN go get github.com/pborman/uuid > /dev/null 2>1 +#RUN go get github.com/rjeczalik/notify > /dev/null 2>1 +#RUN go get github.com/cespare/cp > /dev/null 2>1 +#RUN go get github.com/libp2p/go-libp2p-crypto > /dev/null 2>1 +#RUN go get github.com/kr/pretty > /dev/null 2>1 +#RUN go get github.com/kr/text > /dev/null 2>1 +#RUN go get gopkg.in/check.v1 > /dev/null 2>1 +RUN bash scripts/install_build_tools.sh > /dev/null 2>1 +RUN make > /dev/null 2>1 +#RUN rm -rf harmony + +# Install testing tools +RUN curl -L -o /go/bin/hmy https://harmony.one/hmycli > /dev/null 2>1 && chmod +x /go/bin/hmy > /dev/null 2>1 + +WORKDIR $GOPATH/src/github.com/coinbase + +RUN git clone https://github.com/coinbase/rosetta-cli.git > /dev/null 2>1 +RUN cd rosetta-cli && make install > /dev/null 2>1 + +WORKDIR $GOPATH/src/github.com/harmony-one/harmony/tests + +#COPY scripts scripts +#COPY rpc_tests rpc_tests +#COPY configs configs +#COPY requirements.txt requirements.txt + +WORKDIR $GOPATH/src/github.com/harmony-one/harmony + +# Since we are running as root in Docker, `--break-system-packages` is required +RUN python3 -m pip install -r tests/requirements.txt --break-system-packages +RUN chmod +x tests/scripts/run.sh + + +ENTRYPOINT ["/go/src/github.com/harmony-one/harmony/tests/scripts/run.sh"] diff --git a/api/proto/message/client.go b/api/proto/message/client.go index 20f7103aed..a865c8410b 100644 --- a/api/proto/message/client.go +++ b/api/proto/message/client.go @@ -1,4 +1,4 @@ -package message +package harmonymessage import ( "context" diff --git a/api/proto/message/gen.sh b/api/proto/message/gen.sh index bd667421e3..c4345c0622 100755 --- a/api/proto/message/gen.sh +++ b/api/proto/message/gen.sh @@ -1,3 +1,3 @@ #!/bin/bash -docker run --platform linux/amd64 -v ${PWD}:/tmp ${PROTOC_IMAGE} /tmp/message.proto +docker run --platform linux/amd64 -v ${PWD}:/tmp ${PROTOC_IMAGE} /tmp/harmonymessage.proto diff --git a/api/proto/message/message.pb.go b/api/proto/message/harmonymessage.pb.go similarity index 55% rename from api/proto/message/message.pb.go rename to api/proto/message/harmonymessage.pb.go index 1ba44920ae..ac2bdd3164 100644 --- a/api/proto/message/message.pb.go +++ b/api/proto/message/harmonymessage.pb.go @@ -2,9 +2,9 @@ // versions: // protoc-gen-go v1.30.0 // protoc v3.12.4 -// source: message.proto +// source: harmonymessage.proto -package message +package harmonymessage import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -25,9 +25,9 @@ type ServiceType int32 const ( ServiceType_CONSENSUS ServiceType = 0 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. ServiceType_STAKING ServiceType = 1 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. ServiceType_DRAND ServiceType = 2 ServiceType_CLIENT_SUPPORT ServiceType = 3 ) @@ -59,11 +59,11 @@ func (x ServiceType) String() string { } func (ServiceType) Descriptor() protoreflect.EnumDescriptor { - return file_message_proto_enumTypes[0].Descriptor() + return file_harmonymessage_proto_enumTypes[0].Descriptor() } func (ServiceType) Type() protoreflect.EnumType { - return &file_message_proto_enumTypes[0] + return &file_harmonymessage_proto_enumTypes[0] } func (x ServiceType) Number() protoreflect.EnumNumber { @@ -72,14 +72,14 @@ func (x ServiceType) Number() protoreflect.EnumNumber { // Deprecated: Use ServiceType.Descriptor instead. func (ServiceType) EnumDescriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{0} + return file_harmonymessage_proto_rawDescGZIP(), []int{0} } // MessageType indicates what is the type of this message. type MessageType int32 const ( - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. MessageType_NEWNODE_BEACON_STAKING MessageType = 0 MessageType_ANNOUNCE MessageType = 1 MessageType_PREPARE MessageType = 2 @@ -88,11 +88,11 @@ const ( MessageType_COMMITTED MessageType = 5 MessageType_VIEWCHANGE MessageType = 6 MessageType_NEWVIEW MessageType = 7 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. MessageType_DRAND_INIT MessageType = 10 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. MessageType_DRAND_COMMIT MessageType = 11 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. MessageType_LOTTERY_REQUEST MessageType = 12 // it should be either ENTER or GETPLAYERS but it will be removed later. MessageType_LAST_SIGN_POWER MessageType = 13 ) @@ -140,11 +140,11 @@ func (x MessageType) String() string { } func (MessageType) Descriptor() protoreflect.EnumDescriptor { - return file_message_proto_enumTypes[1].Descriptor() + return file_harmonymessage_proto_enumTypes[1].Descriptor() } func (MessageType) Type() protoreflect.EnumType { - return &file_message_proto_enumTypes[1] + return &file_harmonymessage_proto_enumTypes[1] } func (x MessageType) Number() protoreflect.EnumNumber { @@ -153,17 +153,17 @@ func (x MessageType) Number() protoreflect.EnumNumber { // Deprecated: Use MessageType.Descriptor instead. func (MessageType) EnumDescriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{1} + return file_harmonymessage_proto_rawDescGZIP(), []int{1} } type LotteryRequest_Type int32 const ( - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. LotteryRequest_ENTER LotteryRequest_Type = 0 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. LotteryRequest_RESULT LotteryRequest_Type = 1 - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. LotteryRequest_PICK_WINNER LotteryRequest_Type = 2 ) @@ -192,11 +192,11 @@ func (x LotteryRequest_Type) String() string { } func (LotteryRequest_Type) Descriptor() protoreflect.EnumDescriptor { - return file_message_proto_enumTypes[2].Descriptor() + return file_harmonymessage_proto_enumTypes[2].Descriptor() } func (LotteryRequest_Type) Type() protoreflect.EnumType { - return &file_message_proto_enumTypes[2] + return &file_harmonymessage_proto_enumTypes[2] } func (x LotteryRequest_Type) Number() protoreflect.EnumNumber { @@ -205,7 +205,7 @@ func (x LotteryRequest_Type) Number() protoreflect.EnumNumber { // Deprecated: Use LotteryRequest_Type.Descriptor instead. func (LotteryRequest_Type) EnumDescriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{3, 0} + return file_harmonymessage_proto_rawDescGZIP(), []int{3, 0} } // This is universal message for all communication protocols. @@ -218,8 +218,8 @@ type Message struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ServiceType ServiceType `protobuf:"varint,1,opt,name=service_type,json=serviceType,proto3,enum=message.ServiceType" json:"service_type,omitempty"` - Type MessageType `protobuf:"varint,2,opt,name=type,proto3,enum=message.MessageType" json:"type,omitempty"` + ServiceType ServiceType `protobuf:"varint,1,opt,name=service_type,json=serviceType,proto3,enum=harmonymessage.ServiceType" json:"service_type,omitempty"` + Type MessageType `protobuf:"varint,2,opt,name=type,proto3,enum=harmonymessage.MessageType" json:"type,omitempty"` Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` // Types that are assignable to Request: // @@ -235,7 +235,7 @@ type Message struct { func (x *Message) Reset() { *x = Message{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[0] + mi := &file_harmonymessage_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -248,7 +248,7 @@ func (x *Message) String() string { func (*Message) ProtoMessage() {} func (x *Message) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[0] + mi := &file_harmonymessage_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -261,7 +261,7 @@ func (x *Message) ProtoReflect() protoreflect.Message { // Deprecated: Use Message.ProtoReflect.Descriptor instead. func (*Message) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{0} + return file_harmonymessage_proto_rawDescGZIP(), []int{0} } func (x *Message) GetServiceType() ServiceType { @@ -292,7 +292,7 @@ func (m *Message) GetRequest() isMessage_Request { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *Message) GetStaking() *StakingRequest { if x, ok := x.GetRequest().(*Message_Staking); ok { return x.Staking @@ -307,7 +307,7 @@ func (x *Message) GetConsensus() *ConsensusRequest { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *Message) GetDrand() *DrandRequest { if x, ok := x.GetRequest().(*Message_Drand); ok { return x.Drand @@ -322,7 +322,7 @@ func (x *Message) GetViewchange() *ViewChangeRequest { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *Message) GetLotteryRequest() *LotteryRequest { if x, ok := x.GetRequest().(*Message_LotteryRequest); ok { return x.LotteryRequest @@ -342,7 +342,7 @@ type isMessage_Request interface { } type Message_Staking struct { - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Staking *StakingRequest `protobuf:"bytes,4,opt,name=staking,proto3,oneof"` } @@ -351,7 +351,7 @@ type Message_Consensus struct { } type Message_Drand struct { - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Drand *DrandRequest `protobuf:"bytes,6,opt,name=drand,proto3,oneof"` } @@ -362,7 +362,7 @@ type Message_Viewchange struct { type Message_LotteryRequest struct { // Refactor this later after demo. // - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. LotteryRequest *LotteryRequest `protobuf:"bytes,8,opt,name=lottery_request,json=lotteryRequest,proto3,oneof"` } @@ -387,8 +387,8 @@ type Response struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ServiceType ServiceType `protobuf:"varint,1,opt,name=service_type,json=serviceType,proto3,enum=message.ServiceType" json:"service_type,omitempty"` - Type MessageType `protobuf:"varint,2,opt,name=type,proto3,enum=message.MessageType" json:"type,omitempty"` + ServiceType ServiceType `protobuf:"varint,1,opt,name=service_type,json=serviceType,proto3,enum=harmonymessage.ServiceType" json:"service_type,omitempty"` + Type MessageType `protobuf:"varint,2,opt,name=type,proto3,enum=harmonymessage.MessageType" json:"type,omitempty"` // Types that are assignable to Response: // // *Response_LotteryResponse @@ -398,7 +398,7 @@ type Response struct { func (x *Response) Reset() { *x = Response{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[1] + mi := &file_harmonymessage_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -411,7 +411,7 @@ func (x *Response) String() string { func (*Response) ProtoMessage() {} func (x *Response) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[1] + mi := &file_harmonymessage_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -424,7 +424,7 @@ func (x *Response) ProtoReflect() protoreflect.Message { // Deprecated: Use Response.ProtoReflect.Descriptor instead. func (*Response) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{1} + return file_harmonymessage_proto_rawDescGZIP(), []int{1} } func (x *Response) GetServiceType() ServiceType { @@ -448,7 +448,7 @@ func (m *Response) GetResponse() isResponse_Response { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *Response) GetLotteryResponse() *LotteryResponse { if x, ok := x.GetResponse().(*Response_LotteryResponse); ok { return x.LotteryResponse @@ -461,7 +461,7 @@ type isResponse_Response interface { } type Response_LotteryResponse struct { - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. LotteryResponse *LotteryResponse `protobuf:"bytes,3,opt,name=lottery_response,json=lotteryResponse,proto3,oneof"` } @@ -472,16 +472,16 @@ type LotteryResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Players []string `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Balances []string `protobuf:"bytes,3,rep,name=balances,proto3" json:"balances,omitempty"` } func (x *LotteryResponse) Reset() { *x = LotteryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[2] + mi := &file_harmonymessage_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -494,7 +494,7 @@ func (x *LotteryResponse) String() string { func (*LotteryResponse) ProtoMessage() {} func (x *LotteryResponse) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[2] + mi := &file_harmonymessage_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -507,10 +507,10 @@ func (x *LotteryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use LotteryResponse.ProtoReflect.Descriptor instead. func (*LotteryResponse) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{2} + return file_harmonymessage_proto_rawDescGZIP(), []int{2} } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *LotteryResponse) GetPlayers() []string { if x != nil { return x.Players @@ -518,7 +518,7 @@ func (x *LotteryResponse) GetPlayers() []string { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *LotteryResponse) GetBalances() []string { if x != nil { return x.Balances @@ -531,18 +531,18 @@ type LotteryRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Marked as deprecated in message.proto. - Type LotteryRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=message.LotteryRequest_Type" json:"type,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. + Type LotteryRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=harmonymessage.LotteryRequest_Type" json:"type,omitempty"` + // Deprecated: Marked as deprecated in harmonymessage.proto. PrivateKey string `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` } func (x *LotteryRequest) Reset() { *x = LotteryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[3] + mi := &file_harmonymessage_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -555,7 +555,7 @@ func (x *LotteryRequest) String() string { func (*LotteryRequest) ProtoMessage() {} func (x *LotteryRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[3] + mi := &file_harmonymessage_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -568,10 +568,10 @@ func (x *LotteryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LotteryRequest.ProtoReflect.Descriptor instead. func (*LotteryRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{3} + return file_harmonymessage_proto_rawDescGZIP(), []int{3} } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *LotteryRequest) GetType() LotteryRequest_Type { if x != nil { return x.Type @@ -579,7 +579,7 @@ func (x *LotteryRequest) GetType() LotteryRequest_Type { return LotteryRequest_ENTER } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *LotteryRequest) GetPrivateKey() string { if x != nil { return x.PrivateKey @@ -587,7 +587,7 @@ func (x *LotteryRequest) GetPrivateKey() string { return "" } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *LotteryRequest) GetAmount() int64 { if x != nil { return x.Amount @@ -601,16 +601,16 @@ type StakingRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Transaction []byte `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. NodeId string `protobuf:"bytes,2,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` } func (x *StakingRequest) Reset() { *x = StakingRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[4] + mi := &file_harmonymessage_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -623,7 +623,7 @@ func (x *StakingRequest) String() string { func (*StakingRequest) ProtoMessage() {} func (x *StakingRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[4] + mi := &file_harmonymessage_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -636,10 +636,10 @@ func (x *StakingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StakingRequest.ProtoReflect.Descriptor instead. func (*StakingRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{4} + return file_harmonymessage_proto_rawDescGZIP(), []int{4} } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *StakingRequest) GetTransaction() []byte { if x != nil { return x.Transaction @@ -647,7 +647,7 @@ func (x *StakingRequest) GetTransaction() []byte { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *StakingRequest) GetNodeId() string { if x != nil { return x.NodeId @@ -673,7 +673,7 @@ type ConsensusRequest struct { func (x *ConsensusRequest) Reset() { *x = ConsensusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[5] + mi := &file_harmonymessage_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -686,7 +686,7 @@ func (x *ConsensusRequest) String() string { func (*ConsensusRequest) ProtoMessage() {} func (x *ConsensusRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[5] + mi := &file_harmonymessage_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -699,7 +699,7 @@ func (x *ConsensusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsensusRequest.ProtoReflect.Descriptor instead. func (*ConsensusRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{5} + return file_harmonymessage_proto_rawDescGZIP(), []int{5} } func (x *ConsensusRequest) GetViewId() uint64 { @@ -763,20 +763,20 @@ type DrandRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. ShardId uint32 `protobuf:"varint,1,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. SenderPubkey []byte `protobuf:"bytes,2,opt,name=sender_pubkey,json=senderPubkey,proto3" json:"sender_pubkey,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // Deprecated: Marked as deprecated in message.proto. + // Deprecated: Marked as deprecated in harmonymessage.proto. Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3" json:"payload,omitempty"` } func (x *DrandRequest) Reset() { *x = DrandRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[6] + mi := &file_harmonymessage_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -789,7 +789,7 @@ func (x *DrandRequest) String() string { func (*DrandRequest) ProtoMessage() {} func (x *DrandRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[6] + mi := &file_harmonymessage_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -802,10 +802,10 @@ func (x *DrandRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DrandRequest.ProtoReflect.Descriptor instead. func (*DrandRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{6} + return file_harmonymessage_proto_rawDescGZIP(), []int{6} } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *DrandRequest) GetShardId() uint32 { if x != nil { return x.ShardId @@ -813,7 +813,7 @@ func (x *DrandRequest) GetShardId() uint32 { return 0 } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *DrandRequest) GetSenderPubkey() []byte { if x != nil { return x.SenderPubkey @@ -821,7 +821,7 @@ func (x *DrandRequest) GetSenderPubkey() []byte { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *DrandRequest) GetBlockHash() []byte { if x != nil { return x.BlockHash @@ -829,7 +829,7 @@ func (x *DrandRequest) GetBlockHash() []byte { return nil } -// Deprecated: Marked as deprecated in message.proto. +// Deprecated: Marked as deprecated in harmonymessage.proto. func (x *DrandRequest) GetPayload() []byte { if x != nil { return x.Payload @@ -941,7 +941,7 @@ type ViewChangeRequest struct { func (x *ViewChangeRequest) Reset() { *x = ViewChangeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[8] + mi := &file_harmonymessage_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -954,7 +954,7 @@ func (x *ViewChangeRequest) String() string { func (*ViewChangeRequest) ProtoMessage() {} func (x *ViewChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[8] + mi := &file_harmonymessage_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -967,7 +967,7 @@ func (x *ViewChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ViewChangeRequest.ProtoReflect.Descriptor instead. func (*ViewChangeRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{8} + return file_harmonymessage_proto_rawDescGZIP(), []int{8} } func (x *ViewChangeRequest) GetViewId() uint64 { @@ -1061,213 +1061,204 @@ func (x *ViewChangeRequest) GetPreparedBlock() []byte { return nil } -var File_message_proto protoreflect.FileDescriptor - -var file_message_proto_rawDesc = []byte{ - 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8b, 0x04, 0x0a, 0x07, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, - 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x07, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x12, 0x39, - 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x65, 0x6e, 0x73, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x09, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x12, 0x31, 0x0a, 0x05, 0x64, 0x72, 0x61, - 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x2e, 0x44, 0x72, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, - 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x05, 0x64, 0x72, 0x61, 0x6e, 0x64, 0x12, 0x3c, 0x0a, 0x0a, - 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x56, 0x69, 0x65, 0x77, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0a, - 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x0f, 0x6c, 0x6f, - 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, - 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, - 0x48, 0x00, 0x52, 0x0e, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x47, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x5f, - 0x70, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, - 0x77, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x6c, 0x61, - 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x49, 0x0a, 0x10, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, - 0x79, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, - 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, - 0x52, 0x0f, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, - 0x0f, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x1e, - 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xc3, - 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1c, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x42, 0x02, 0x18, - 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0d, 0x0a, 0x05, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01, 0x12, - 0x0e, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, 0x12, - 0x13, 0x0a, 0x0b, 0x50, 0x49, 0x43, 0x4b, 0x5f, 0x57, 0x49, 0x4e, 0x4e, 0x45, 0x52, 0x10, 0x02, - 0x1a, 0x02, 0x08, 0x01, 0x22, 0x53, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, - 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x07, - 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, - 0x01, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x89, 0x02, 0x0a, 0x10, 0x43, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, - 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, - 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, - 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x12, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x42, - 0x69, 0x74, 0x6d, 0x61, 0x70, 0x22, 0x97, 0x01, 0x0a, 0x0c, 0x44, 0x72, 0x61, 0x6e, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x21, - 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, - 0x68, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, - 0xa0, 0x01, 0x0a, 0x14, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, 0x77, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x70, - 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x70, 0x72, 0x65, 0x70, 0x61, - 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x49, 0x64, 0x22, 0xad, 0x03, 0x0a, 0x11, 0x56, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, - 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, - 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, - 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x25, 0x0a, - 0x0e, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, 0x5f, 0x73, - 0x69, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, - 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x32, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, - 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x32, 0x41, 0x67, 0x67, 0x73, 0x69, - 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x32, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x32, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, - 0x1d, 0x0a, 0x0a, 0x6d, 0x33, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x33, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x12, 0x1b, - 0x0a, 0x09, 0x6d, 0x33, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x08, 0x6d, 0x33, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, - 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x2a, 0x50, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x10, 0x00, - 0x12, 0x0f, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, 0x02, 0x08, - 0x01, 0x12, 0x0d, 0x0a, 0x05, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, - 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x55, 0x50, 0x50, 0x4f, - 0x52, 0x54, 0x10, 0x03, 0x2a, 0xe6, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x16, 0x4e, 0x45, 0x57, 0x4e, 0x4f, 0x44, 0x45, 0x5f, - 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x00, - 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, - 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x02, 0x12, - 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, - 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, - 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x49, 0x45, 0x57, - 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x45, 0x57, 0x56, - 0x49, 0x45, 0x57, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0a, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x5f, 0x49, - 0x4e, 0x49, 0x54, 0x10, 0x0a, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x44, 0x52, 0x41, - 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0b, 0x1a, 0x02, 0x08, 0x01, 0x12, - 0x17, 0x0a, 0x0f, 0x4c, 0x4f, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, - 0x53, 0x54, 0x10, 0x0c, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x41, 0x53, 0x54, - 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x10, 0x0d, 0x32, 0x41, 0x0a, - 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, - 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x10, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x11, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +var File_harmonymessage_proto protoreflect.FileDescriptor + +var file_harmonymessage_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xf3, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, + 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x07, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, + 0x67, 0x12, 0x40, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x12, 0x38, 0x0a, 0x05, 0x64, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x2e, 0x44, 0x72, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x05, 0x64, 0x72, 0x61, 0x6e, 0x64, 0x12, 0x43, 0x0a, + 0x0a, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x2e, 0x56, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, + 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, + 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x48, + 0x00, 0x52, 0x0e, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xd9, 0x01, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, + 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x6c, 0x6f, + 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x0f, 0x6c, 0x6f, 0x74, + 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x0f, 0x4c, 0x6f, 0x74, 0x74, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x07, 0x70, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x62, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, + 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xca, 0x01, 0x0a, 0x0e, 0x4c, 0x6f, + 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x72, + 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x42, + 0x02, 0x18, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0b, 0x70, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1a, + 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x0a, 0x04, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x05, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x1a, 0x02, 0x08, + 0x01, 0x12, 0x0e, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x1a, 0x02, 0x08, + 0x01, 0x12, 0x13, 0x0a, 0x0b, 0x50, 0x49, 0x43, 0x4b, 0x5f, 0x57, 0x49, 0x4e, 0x4e, 0x45, 0x52, + 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x22, 0x53, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, + 0x01, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, + 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x02, 0x18, 0x01, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x89, 0x02, 0x0a, 0x10, + 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x12, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x22, 0x97, 0x01, 0x0a, 0x0c, 0x44, 0x72, 0x61, 0x6e, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, + 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x12, 0x21, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x22, 0xad, 0x03, 0x0a, 0x11, 0x56, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, + 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x25, 0x0a, 0x0e, + 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, 0x5f, 0x73, 0x69, + 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, 0x53, + 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x32, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x32, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, + 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x32, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x32, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x1d, + 0x0a, 0x0a, 0x6d, 0x33, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x33, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x6d, 0x33, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x6d, 0x33, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x2a, 0x50, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x10, 0x00, 0x12, + 0x0f, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, + 0x12, 0x0d, 0x0a, 0x05, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x12, + 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, + 0x54, 0x10, 0x03, 0x2a, 0xd1, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x16, 0x4e, 0x45, 0x57, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x42, + 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x1a, + 0x02, 0x08, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x10, + 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x02, 0x12, 0x0c, + 0x0a, 0x08, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, + 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x4d, + 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x49, 0x45, 0x57, 0x43, + 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x45, 0x57, 0x56, 0x49, + 0x45, 0x57, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0a, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x5f, 0x49, 0x4e, + 0x49, 0x54, 0x10, 0x0a, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x44, 0x52, 0x41, 0x4e, + 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0b, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x17, + 0x0a, 0x0f, 0x4c, 0x4f, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, + 0x54, 0x10, 0x0c, 0x1a, 0x02, 0x08, 0x01, 0x32, 0x4f, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x12, 0x17, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x68, + 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x13, 0x5a, 0x11, 0x2e, 0x2f, 0x3b, 0x68, + 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_message_proto_rawDescOnce sync.Once - file_message_proto_rawDescData = file_message_proto_rawDesc + file_harmonymessage_proto_rawDescOnce sync.Once + file_harmonymessage_proto_rawDescData = file_harmonymessage_proto_rawDesc ) -func file_message_proto_rawDescGZIP() []byte { - file_message_proto_rawDescOnce.Do(func() { - file_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_message_proto_rawDescData) +func file_harmonymessage_proto_rawDescGZIP() []byte { + file_harmonymessage_proto_rawDescOnce.Do(func() { + file_harmonymessage_proto_rawDescData = protoimpl.X.CompressGZIP(file_harmonymessage_proto_rawDescData) }) - return file_message_proto_rawDescData -} - -var file_message_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 9) -var file_message_proto_goTypes = []interface{}{ - (ServiceType)(0), // 0: message.ServiceType - (MessageType)(0), // 1: message.MessageType - (LotteryRequest_Type)(0), // 2: message.LotteryRequest.Type - (*Message)(nil), // 3: message.Message - (*Response)(nil), // 4: message.Response - (*LotteryResponse)(nil), // 5: message.LotteryResponse - (*LotteryRequest)(nil), // 6: message.LotteryRequest - (*StakingRequest)(nil), // 7: message.StakingRequest - (*ConsensusRequest)(nil), // 8: message.ConsensusRequest - (*DrandRequest)(nil), // 9: message.DrandRequest + return file_harmonymessage_proto_rawDescData +} + +var file_harmonymessage_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_harmonymessage_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_harmonymessage_proto_goTypes = []interface{}{ + (ServiceType)(0), // 0: harmonymessage.ServiceType + (MessageType)(0), // 1: harmonymessage.MessageType + (LotteryRequest_Type)(0), // 2: harmonymessage.LotteryRequest.Type + (*Message)(nil), // 3: harmonymessage.Message + (*Response)(nil), // 4: harmonymessage.Response + (*LotteryResponse)(nil), // 5: harmonymessage.LotteryResponse + (*LotteryRequest)(nil), // 6: harmonymessage.LotteryRequest + (*StakingRequest)(nil), // 7: harmonymessage.StakingRequest + (*ConsensusRequest)(nil), // 8: harmonymessage.ConsensusRequest + (*DrandRequest)(nil), // 9: harmonymessage.DrandRequest (*LastSignPowerRequest)(nil), // 10: message.LastSignPowerRequest - (*ViewChangeRequest)(nil), // 11: message.ViewChangeRequest -} -var file_message_proto_depIdxs = []int32{ - 0, // 0: message.Message.service_type:type_name -> message.ServiceType - 1, // 1: message.Message.type:type_name -> message.MessageType - 7, // 2: message.Message.staking:type_name -> message.StakingRequest - 8, // 3: message.Message.consensus:type_name -> message.ConsensusRequest - 9, // 4: message.Message.drand:type_name -> message.DrandRequest - 11, // 5: message.Message.viewchange:type_name -> message.ViewChangeRequest - 6, // 6: message.Message.lottery_request:type_name -> message.LotteryRequest + (*ViewChangeRequest)(nil), // 11: harmonymessage.ViewChangeRequest +} +var file_harmonymessage_proto_depIdxs = []int32{ + 0, // 0: harmonymessage.Message.service_type:type_name -> harmonymessage.ServiceType + 1, // 1: harmonymessage.Message.type:type_name -> harmonymessage.MessageType + 7, // 2: harmonymessage.Message.staking:type_name -> harmonymessage.StakingRequest + 8, // 3: harmonymessage.Message.consensus:type_name -> harmonymessage.ConsensusRequest + 9, // 4: harmonymessage.Message.drand:type_name -> harmonymessage.DrandRequest + 11, // 5: harmonymessage.Message.viewchange:type_name -> harmonymessage.ViewChangeRequest + 6, // 6: harmonymessage.Message.lottery_request:type_name -> harmonymessage.LotteryRequest 10, // 7: message.Message.last_sign_power:type_name -> message.LastSignPowerRequest - 0, // 8: message.Response.service_type:type_name -> message.ServiceType - 1, // 9: message.Response.type:type_name -> message.MessageType - 5, // 10: message.Response.lottery_response:type_name -> message.LotteryResponse - 2, // 11: message.LotteryRequest.type:type_name -> message.LotteryRequest.Type - 3, // 12: message.ClientService.Process:input_type -> message.Message - 4, // 13: message.ClientService.Process:output_type -> message.Response + 0, // 8: harmonymessage.Response.service_type:type_name -> harmonymessage.ServiceType + 1, // 9: harmonymessage.Response.type:type_name -> harmonymessage.MessageType + 5, // 10: harmonymessage.Response.lottery_response:type_name -> harmonymessage.LotteryResponse + 2, // 11: harmonymessage.LotteryRequest.type:type_name -> harmonymessage.LotteryRequest.Type + 3, // 12: harmonymessage.ClientService.Process:input_type -> harmonymessage.Message + 4, // 13: harmonymessage.ClientService.Process:output_type -> harmonymessage.Response 13, // [13:14] is the sub-list for method output_type 12, // [12:13] is the sub-list for method input_type 12, // [12:12] is the sub-list for extension type_name @@ -1275,13 +1266,13 @@ var file_message_proto_depIdxs = []int32{ 0, // [0:12] is the sub-list for field type_name } -func init() { file_message_proto_init() } -func file_message_proto_init() { - if File_message_proto != nil { +func init() { file_harmonymessage_proto_init() } +func file_harmonymessage_proto_init() { + if File_harmonymessage_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Message); i { case 0: return &v.state @@ -1293,7 +1284,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Response); i { case 0: return &v.state @@ -1305,7 +1296,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LotteryResponse); i { case 0: return &v.state @@ -1317,7 +1308,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LotteryRequest); i { case 0: return &v.state @@ -1329,7 +1320,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StakingRequest); i { case 0: return &v.state @@ -1341,7 +1332,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConsensusRequest); i { case 0: return &v.state @@ -1353,7 +1344,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DrandRequest); i { case 0: return &v.state @@ -1365,7 +1356,7 @@ func file_message_proto_init() { return nil } } - file_message_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LastSignPowerRequest); i { case 0: return &v.state @@ -1390,7 +1381,7 @@ func file_message_proto_init() { } } } - file_message_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_harmonymessage_proto_msgTypes[0].OneofWrappers = []interface{}{ (*Message_Staking)(nil), (*Message_Consensus)(nil), (*Message_Drand)(nil), @@ -1398,26 +1389,26 @@ func file_message_proto_init() { (*Message_LotteryRequest)(nil), (*Message_LastSignPower)(nil), } - file_message_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_harmonymessage_proto_msgTypes[1].OneofWrappers = []interface{}{ (*Response_LotteryResponse)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_message_proto_rawDesc, + RawDescriptor: file_harmonymessage_proto_rawDesc, NumEnums: 3, NumMessages: 9, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_message_proto_goTypes, - DependencyIndexes: file_message_proto_depIdxs, - EnumInfos: file_message_proto_enumTypes, - MessageInfos: file_message_proto_msgTypes, + GoTypes: file_harmonymessage_proto_goTypes, + DependencyIndexes: file_harmonymessage_proto_depIdxs, + EnumInfos: file_harmonymessage_proto_enumTypes, + MessageInfos: file_harmonymessage_proto_msgTypes, }.Build() - File_message_proto = out.File - file_message_proto_rawDesc = nil - file_message_proto_goTypes = nil - file_message_proto_depIdxs = nil + File_harmonymessage_proto = out.File + file_harmonymessage_proto_rawDesc = nil + file_harmonymessage_proto_goTypes = nil + file_harmonymessage_proto_depIdxs = nil } diff --git a/api/proto/message/message.proto b/api/proto/message/harmonymessage.proto similarity index 98% rename from api/proto/message/message.proto rename to api/proto/message/harmonymessage.proto index 34e58a9176..72a2c81474 100644 --- a/api/proto/message/message.proto +++ b/api/proto/message/harmonymessage.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package message; -option go_package="./;message"; +package harmonymessage; +option go_package="./;harmonymessage"; // Client is the service used for any client-facing requests. diff --git a/api/proto/message/message_grpc.pb.go b/api/proto/message/harmonymessage_grpc.pb.go similarity index 94% rename from api/proto/message/message_grpc.pb.go rename to api/proto/message/harmonymessage_grpc.pb.go index 82a08b9b3d..79952ca728 100644 --- a/api/proto/message/message_grpc.pb.go +++ b/api/proto/message/harmonymessage_grpc.pb.go @@ -2,9 +2,9 @@ // versions: // - protoc-gen-go-grpc v1.3.0 // - protoc v3.12.4 -// source: message.proto +// source: harmonymessage.proto -package message +package harmonymessage import ( context "context" @@ -19,7 +19,7 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ClientService_Process_FullMethodName = "/message.ClientService/Process" + ClientService_Process_FullMethodName = "/harmonymessage.ClientService/Process" ) // ClientServiceClient is the client API for ClientService service. @@ -96,7 +96,7 @@ func _ClientService_Process_Handler(srv interface{}, ctx context.Context, dec fu // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var ClientService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "message.ClientService", + ServiceName: "harmonymessage.ClientService", HandlerType: (*ClientServiceServer)(nil), Methods: []grpc.MethodDesc{ { @@ -105,5 +105,5 @@ var ClientService_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "message.proto", + Metadata: "harmonymessage.proto", } diff --git a/api/proto/message/message.go b/api/proto/message/message.go index 22f91a10e7..d6dec2bbd9 100644 --- a/api/proto/message/message.go +++ b/api/proto/message/message.go @@ -1,3 +1,3 @@ -package message +package harmonymessage //go:generate ./gen.sh diff --git a/api/proto/message/server.go b/api/proto/message/server.go index 695bf907f9..217fc7f81f 100644 --- a/api/proto/message/server.go +++ b/api/proto/message/server.go @@ -1,4 +1,4 @@ -package message +package harmonymessage import ( "context" diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 6a5e3716d9..f6ab6481eb 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -160,7 +160,7 @@ func main() { } fmt.Printf("bootnode BN_MA=%s", - fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, host.GetID().Pretty()), + fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, host.GetID().String()), ) host.Start() diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index b8d6eb6832..04038f943c 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -440,7 +440,7 @@ func setupNodeAndRun(hc harmonyconfig.HarmonyConfig) { Str("Role", currentNode.NodeConfig.Role().String()). Str("Version", getHarmonyVersion()). Str("multiaddress", - fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", hc.P2P.IP, hc.P2P.Port, myHost.GetID().Pretty()), + fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", hc.P2P.IP, hc.P2P.Port, myHost.GetID().String()), ). Msg(startMsg) @@ -959,7 +959,7 @@ func setupPrometheusService(node *node.Node, hc harmonyconfig.HarmonyConfig, sid Legacy: hc.General.NoStaking, NodeType: hc.General.NodeType, Shard: sid, - Instance: myHost.GetID().Pretty(), + Instance: myHost.GetID().String(), } if hc.General.RunElasticMode { diff --git a/go.mod b/go.mod index 7f17e5b912..eaaf133588 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/harmony-one/harmony -go 1.19 +go 1.21 require ( github.com/RoaringBitmap/roaring v1.2.3 @@ -20,7 +20,7 @@ require ( 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 + github.com/gorilla/websocket v1.5.1 github.com/harmony-one/abool v1.0.1 github.com/harmony-one/bls v0.0.6 github.com/harmony-one/taggedrlp v0.1.4 @@ -29,16 +29,16 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/ipfs/go-ds-badger v0.3.0 github.com/json-iterator/go v1.1.12 - github.com/libp2p/go-libp2p v0.27.9 - github.com/libp2p/go-libp2p-kad-dht v0.21.0 - github.com/libp2p/go-libp2p-pubsub v0.9.3 - github.com/multiformats/go-multiaddr v0.9.0 + github.com/libp2p/go-libp2p v0.35.1 + github.com/libp2p/go-libp2p-kad-dht v0.25.2 + github.com/libp2p/go-libp2p-pubsub v0.11.0 + github.com/multiformats/go-multiaddr v0.12.4 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/pborman/uuid v1.2.0 github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_golang v1.19.1 github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 github.com/rjeczalik/notify v0.9.2 github.com/rs/cors v1.7.0 @@ -46,18 +46,18 @@ require ( github.com/spf13/cobra v1.5.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.14.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tikv/client-go/v2 v2.0.1 github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee go.uber.org/ratelimit v0.1.0 - go.uber.org/zap v1.24.0 - golang.org/x/crypto v0.14.0 - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.4.0 - golang.org/x/sys v0.13.0 // indirect - golang.org/x/time v0.3.0 - golang.org/x/tools v0.14.0 // indirect + go.uber.org/zap v1.27.0 + golang.org/x/crypto v0.23.0 + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 + golang.org/x/sys v0.20.0 // indirect + golang.org/x/time v0.5.0 + golang.org/x/tools v0.21.0 // indirect google.golang.org/grpc v1.55.0 google.golang.org/protobuf v1.34.2 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c @@ -73,7 +73,7 @@ require ( 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 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 ) require ( @@ -82,7 +82,7 @@ require ( github.com/DataDog/zstd v1.5.5 // indirect github.com/OpenPeeDeeP/depguard v1.0.1 // indirect github.com/VictoriaMetrics/metrics v1.23.1 // indirect - github.com/benbjohnson/clock v1.3.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/bombsimon/wsl/v2 v2.0.0 // indirect @@ -98,7 +98,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.3.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/badger v1.6.2 // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect @@ -107,13 +107,15 @@ require ( github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/fatih/color v1.13.0 // indirect - github.com/flynn/noise v1.0.0 // indirect + github.com/flynn/noise v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-critic/go-critic v0.4.0 // indirect github.com/go-lintpack/lintpack v0.5.2 // indirect + github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect @@ -145,57 +147,55 @@ require ( github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 // 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/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/ipfs/boxo v0.10.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-datastore v0.6.0 // indirect - github.com/ipfs/go-ipfs-util v0.0.2 // indirect - github.com/ipfs/go-ipns v0.2.0 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/ipld/go-ipld-prime v0.19.0 // indirect + github.com/ipld/go-ipld-prime v0.20.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kisielk/gotool v1.0.0 // indirect - github.com/klauspost/compress v1.17.1 // indirect - github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/klauspost/compress v1.17.8 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect - github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect + github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect github.com/libp2p/go-libp2p-record v0.2.0 // indirect - github.com/libp2p/go-mplex v0.7.0 // indirect + github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.1.0 // indirect + github.com/libp2p/go-nat v0.2.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/libp2p/go-reuseport v0.2.0 // indirect - github.com/libp2p/go-yamux/v4 v4.0.0 // indirect + github.com/libp2p/go-reuseport v0.4.0 // indirect + github.com/libp2p/go-yamux/v4 v4.0.1 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.53 // indirect + github.com/miekg/dns v1.1.58 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -206,13 +206,13 @@ require ( github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.8.1 // indirect - github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/multiformats/go-multistream v0.4.1 // indirect + github.com/multiformats/go-multicodec v0.9.0 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect - github.com/onsi/ginkgo/v2 v2.9.2 // indirect - github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/onsi/ginkgo/v2 v2.15.0 // indirect + github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect @@ -220,17 +220,31 @@ require ( github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00 // indirect github.com/pingcap/kvproto v0.0.0-20220106070556-3fa8fa04f898 // indirect github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee // indirect + github.com/pion/datachannel v1.5.6 // indirect + github.com/pion/dtls/v2 v2.2.11 // indirect + github.com/pion/ice/v2 v2.3.25 // indirect + github.com/pion/interceptor v0.1.29 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/mdns v0.0.12 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.14 // indirect + github.com/pion/rtp v1.8.6 // indirect + github.com/pion/sctp v1.8.16 // indirect + github.com/pion/sdp/v3 v3.0.9 // indirect + github.com/pion/srtp/v2 v2.0.18 // indirect + github.com/pion/stun v0.6.1 // indirect + github.com/pion/transport/v2 v2.2.5 // indirect + github.com/pion/turn/v2 v2.1.6 // indirect + github.com/pion/webrtc/v3 v3.2.40 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.44.0 // indirect + github.com/polydawn/refmt v0.89.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/tsdb v0.7.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.3.3 // indirect - github.com/quic-go/qtls-go1-20 v0.2.3 // indirect - github.com/quic-go/quic-go v0.33.1 // indirect - github.com/quic-go/webtransport-go v0.5.2 // indirect + github.com/quic-go/quic-go v0.44.0 // indirect + github.com/quic-go/webtransport-go v0.8.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect @@ -243,7 +257,7 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/tikv/pd/client v0.0.0-20220216070739-26c668271201 // indirect github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e // indirect @@ -260,23 +274,27 @@ require ( github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.16.1 // indirect - go.uber.org/fx v1.19.2 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect + go.opentelemetry.io/otel/trace v1.16.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/dig v1.17.1 // indirect + go.uber.org/fx v1.21.1 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/term v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + gonum.org/v1/gonum v0.13.0 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.0.1-2020.1.5 // indirect - lukechampine.com/blake3 v1.1.7 // indirect + lukechampine.com/blake3 v1.2.1 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f // indirect - nhooyr.io/websocket v1.8.7 // indirect sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 // indirect ) diff --git a/go.sum b/go.sum index fe61a05100..21b4783240 100644 --- a/go.sum +++ b/go.sum @@ -132,8 +132,9 @@ github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw= github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -266,9 +267,10 @@ github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17 github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= @@ -337,12 +339,13 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+ github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -362,11 +365,8 @@ github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= @@ -395,7 +395,11 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -404,15 +408,9 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= @@ -447,19 +445,16 @@ github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUD github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA= github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -490,6 +485,7 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -578,14 +574,14 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -604,15 +600,17 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= -github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo= +github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -628,8 +626,9 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= 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/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= @@ -676,8 +675,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= -github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -692,7 +691,6 @@ github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25 github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= @@ -715,6 +713,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY= +github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= @@ -727,16 +727,14 @@ github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupV github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= -github.com/ipfs/go-ipns v0.2.0 h1:BgmNtQhqOw5XEZ8RAfWEpK4DhqaYiuP6h71MhIp7xXU= -github.com/ipfs/go-ipns v0.2.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/ipld/go-ipld-prime v0.19.0 h1:5axC7rJmPc17Emw6TelxGwnzALk0PdupZ2oj2roDj04= -github.com/ipld/go-ipld-prime v0.19.0/go.mod h1:Q9j3BaVXwaA3o5JUDNvptDDr/x8+F7FG6XJ8WI3ILg4= +github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g= +github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/httpexpect/v2 v2.3.1/go.mod h1:ICTf89VBKSD3KB0fsyyHviKF8G8hyepP0dOXJPWz3T0= @@ -816,28 +814,24 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.10/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= -github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= -github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -867,8 +861,6 @@ github.com/ledgerwatch/erigon-lib v0.0.0-20230607152933-42c9c28cac68 h1:eKTHu42q github.com/ledgerwatch/erigon-lib v0.0.0-20230607152933-42c9c28cac68/go.mod h1:gV87KL7+CmJ31bLSk0FbCnowHYi6w7kF8Q1vyiwttqg= github.com/ledgerwatch/log/v3 v3.8.0 h1:gCpp7uGtIerEz1jKVPeDnbIopFPud9ZnCpBLlLBGqPU= github.com/ledgerwatch/log/v3 v3.8.0/go.mod h1:J2Jl6zV/58LeA6LTaVVnCGyf1/cYYSEOOLHY4ZN8S2A= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -878,33 +870,32 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.27.9 h1:n5p5bQD469v7I/1qncaHDq0BeSx4iT2fHF3NyNuKOmY= -github.com/libp2p/go-libp2p v0.27.9/go.mod h1:Tdx7ZuJl9NE78PkB4FjPVbf6kaQNOh2ppU/OVvVB6Wc= -github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= -github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= -github.com/libp2p/go-libp2p-kad-dht v0.21.0 h1:J0Yd22VA+sk0CJRGMgtfHvLVIkZDyJ3AJGiljywIw5U= -github.com/libp2p/go-libp2p-kad-dht v0.21.0/go.mod h1:Bhm9diAFmc6qcWAr084bHNL159srVZRKADdp96Qqd1I= -github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA= -github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U= -github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= -github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= +github.com/libp2p/go-libp2p v0.35.1 h1:Hm7Ub2BF+GCb14ojcsEK6WAy5it5smPDK02iXSZLl50= +github.com/libp2p/go-libp2p v0.35.1/go.mod h1:Dnkgba5hsfSv5dvvXC8nfqk44hH0gIKKno+HOMU0fdc= +github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= +github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-kad-dht v0.25.2 h1:FOIk9gHoe4YRWXTu8SY9Z1d0RILol0TrtApsMDPjAVQ= +github.com/libp2p/go-libp2p-kad-dht v0.25.2/go.mod h1:6za56ncRHYXX4Nc2vn8z7CZK0P4QiMcrn77acKLM2Oo= +github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0= +github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0= +github.com/libp2p/go-libp2p-pubsub v0.11.0 h1:+JvS8Kty0OiyUiN0i8H5JbaCgjnJTRnTHe4rU88dLFc= +github.com/libp2p/go-libp2p-pubsub v0.11.0/go.mod h1:QEb+hEV9WL9wCiUAnpY29FZR6W3zK8qYlaml8R4q6gQ= github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= +github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsah7NLw3Qs2zjUV78T0= +github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= -github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= -github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= +github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= -github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= -github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= +github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= +github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= +github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ= +github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -944,8 +935,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -955,7 +946,6 @@ github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4f github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= @@ -967,8 +957,8 @@ github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8m github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= -github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= +github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -978,8 +968,8 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4S github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -1009,7 +999,6 @@ github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3P github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= @@ -1021,24 +1010,22 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9 github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= -github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= +github.com/multiformats/go-multiaddr v0.12.4 h1:rrKqpY9h+n80EwhhC/kkcunCZZ7URIF8yN1WEUt2Hvc= +github.com/multiformats/go-multiaddr v0.12.4/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= -github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= +github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= +github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= -github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= +github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1067,8 +1054,9 @@ github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -1083,8 +1071,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= -github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1092,9 +1080,11 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= +github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1134,6 +1124,51 @@ github.com/pingcap/kvproto v0.0.0-20220106070556-3fa8fa04f898/go.mod h1:IOdRDPLy github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee h1:VO2t6IBpfvW34TdtD/G10VvnGqjLic1jzOuHjUb5VqM= github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= +github.com/pion/datachannel v1.5.6 h1:1IxKJntfSlYkpUj8LlYRSWpYiTTC02nUrOE8T3DqGeg= +github.com/pion/datachannel v1.5.6/go.mod h1:1eKT6Q85pRnr2mHiWHxJwO50SfZRtWHTsNIVb/NfGW4= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/dtls/v2 v2.2.11 h1:9U/dpCYl1ySttROPWJgqWKEylUdT0fXp/xst6JwY5Ks= +github.com/pion/dtls/v2 v2.2.11/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/ice/v2 v2.3.25 h1:M5rJA07dqhi3nobJIg+uPtcVjFECTrhcR3n0ns8kDZs= +github.com/pion/ice/v2 v2.3.25/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw= +github.com/pion/interceptor v0.1.29 h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M= +github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/z/Zms/6T4= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= +github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= +github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= +github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= +github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/rtp v1.8.6 h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw= +github.com/pion/rtp v1.8.6/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/sctp v1.8.13/go.mod h1:YKSgO/bO/6aOMP9LCie1DuD7m+GamiK2yIiPM6vH+GA= +github.com/pion/sctp v1.8.16 h1:PKrMs+o9EMLRvFfXq59WFsC+V8mN1wnKzqrv+3D/gYY= +github.com/pion/sctp v1.8.16/go.mod h1:P6PbDVA++OJMrVNg2AL3XtYHV4uD6dvfyOovCgMs0PE= +github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= +github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= +github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo= +github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= +github.com/pion/transport v0.13.1 h1:/UH5yLeQtwm2VZIPjxwnNFxjS4DFhyLfS4GlfuKUzfA= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= +github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.5 h1:iyi25i/21gQck4hfRhomF6SktmUQjRsRW4WJdhfc3Kc= +github.com/pion/transport/v2 v2.2.5/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= +github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= +github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= +github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc= +github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= +github.com/pion/webrtc/v3 v3.2.40 h1:Wtfi6AZMQg+624cvCXUuSmrKWepSB7zfgYDOYqsSOVU= +github.com/pion/webrtc/v3 v3.2.40/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/OgpoGGJqFY= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1144,8 +1179,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls= -github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= +github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1157,16 +1192,16 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1177,8 +1212,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1195,14 +1230,10 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= -github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI= -github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/quic-go/quic-go v0.33.1 h1:EVsG7O/7FVZI8Za71GzpHDoWpBTKdjDv1/x0KFcckho= -github.com/quic-go/quic-go v0.33.1/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= -github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= -github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= +github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0= +github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek= +github.com/quic-go/webtransport-go v0.8.0 h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg= +github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YVSlwHohQsuac9WaM= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= @@ -1334,8 +1365,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1348,8 +1380,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1392,18 +1426,17 @@ github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2n github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo= github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= +github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= @@ -1430,8 +1463,8 @@ github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZ github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= -github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= @@ -1480,6 +1513,12 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1487,17 +1526,20 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= -go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= -go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= -go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= +go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.21.1 h1:RqBh3cYdzZS0uqwVeEjOX2p73dddLpym315myy/Bpb0= +go.uber.org/fx v1.21.1/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -1519,8 +1561,8 @@ go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1560,8 +1602,14 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1578,8 +1626,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1611,15 +1659,15 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1687,8 +1735,16 @@ golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1721,8 +1777,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1737,10 +1793,8 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1826,7 +1880,6 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1840,17 +1893,31 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1863,8 +1930,12 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1874,8 +1945,8 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1962,8 +2033,9 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1973,6 +2045,8 @@ gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJ gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= +gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= @@ -2109,10 +2183,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2168,8 +2240,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k= honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= -lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= +lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= @@ -2177,8 +2249,6 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4= mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/p2p/host.go b/p2p/host.go index df2276ab7c..7f6cfd7046 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -37,7 +37,6 @@ import ( "github.com/libp2p/go-libp2p/core/sec/insecure" basichost "github.com/libp2p/go-libp2p/p2p/host/basic" - mplex "github.com/libp2p/go-libp2p/p2p/muxer/mplex" yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux" noise "github.com/libp2p/go-libp2p/p2p/security/noise" tls "github.com/libp2p/go-libp2p/p2p/security/tls" @@ -224,8 +223,8 @@ func NewHost(cfg HostConfig) (Host, error) { switch v { case "yamux": p2pHostConfig = append(p2pHostConfig, YamuxC()) - case "mplex": - p2pHostConfig = append(p2pHostConfig, MplexC()) + //case "mplex": + // p2pHostConfig = append(p2pHostConfig, MplexC()) default: cancel() utils.Logger().Error(). @@ -320,7 +319,7 @@ func NewHost(cfg HostConfig) (Host, error) { } self.PeerID = p2pHost.ID() - subLogger := utils.Logger().With().Str("hostID", p2pHost.ID().Pretty()).Logger() + subLogger := utils.Logger().With().Str("hostID", p2pHost.ID().String()).Logger() banned := blockedpeers.NewManager(1024) security := security.NewManager(cfg.MaxConnPerIP, int(cfg.MaxPeers), banned) @@ -353,9 +352,9 @@ func YamuxC() libp2p.Option { return libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport) } -func MplexC() libp2p.Option { - return libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport) -} +//func MplexC() libp2p.Option { +// return libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport) +//} func NoiseC() libp2p.Option { return libp2p.Security(noise.ID, noise.New) @@ -589,7 +588,7 @@ func (host *HostV2) Network() libp2p_network.Network { // ConnectHostPeer connects to peer host func (host *HostV2) ConnectHostPeer(peer Peer) error { ctx := context.Background() - addr := fmt.Sprintf("/ip4/%s/tcp/%s/ipfs/%s", peer.IP, peer.Port, peer.PeerID.Pretty()) + addr := fmt.Sprintf("/ip4/%s/tcp/%s/ipfs/%s", peer.IP, peer.Port, peer.PeerID.String()) peerAddr, err := ma.NewMultiaddr(addr) if err != nil { host.logger.Error().Err(err).Interface("peer", peer).Msg("ConnectHostPeer") diff --git a/scripts/travis_rpc_checker.sh b/scripts/travis_rpc_checker.sh index ada3f986db..9bf0203d3d 100755 --- a/scripts/travis_rpc_checker.sh +++ b/scripts/travis_rpc_checker.sh @@ -5,8 +5,9 @@ echo $TRAVIS_PULL_REQUEST_BRANCH DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo $DIR echo $GOPATH -cd tests -echo "$DIR/../:/go/src/github.com/harmony-one/harmony" -docker build -t harmonyone/localnet-test . +pwd +#echo "$DIR/../:/go/src/github.com/harmony-one/harmony" +docker build --progress=plain -t harmonyone/localnet-test -f Tests.Dockerfile . -docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -n \ No newline at end of file +#docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -n +docker run harmonyone/localnet-test -n \ No newline at end of file diff --git a/tests/Dockerfile b/tests/Dockerfile index cac0b755e8..30640b0bfa 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19 +FROM golang:1.21 WORKDIR $GOPATH/src/github.com/harmony-one @@ -10,11 +10,11 @@ RUN apt clean > /dev/null 2>1 RUN apt update > /dev/null 2>1 RUN apt upgrade -y > /dev/null 2>1 RUN apt update -y > /dev/null 2>1 -RUN apt install -y unzip libgmp-dev libssl-dev curl git jq make gcc g++ bash sudo python3 python3-pip > /dev/null 2>1 +RUN apt install -y unzip libgmp-dev libssl-dev curl git jq make gcc g++ bash sudo python3 python3-pip -RUN git clone https://github.com/harmony-one/harmony.git > /dev/null 2>1 \ - && git clone https://github.com/harmony-one/bls.git > /dev/null 2>1 \ - && git clone https://github.com/harmony-one/mcl.git > /dev/null 2>1 +#RUN #git clone https://github.com/harmony-one/harmony.git > /dev/null 2>1 \ +RUN git clone https://github.com/harmony-one/bls.git > /dev/null 2>1 +RUN git clone https://github.com/harmony-one/mcl.git > /dev/null 2>1 # Fix complaints about Docker / root / user ownership for Golang "VCS stamping" # https://github.com/golang/go/blob/3900ba4baf0e3b309a55b5ac4dd25f709df09772/src/cmd/go/internal/vcs/vcs.go @@ -23,9 +23,19 @@ RUN git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/ && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/mcl > /dev/null 2>1 # Build to fetch all dependencies for faster test builds -RUN cd harmony > /dev/null 2>1 && go mod tidy > /dev/null 2>1 && go get github.com/pborman/uuid > /dev/null 2>1 && go get github.com/rjeczalik/notify > /dev/null 2>1 \ - && go get github.com/cespare/cp > /dev/null 2>1 && go get github.com/libp2p/go-libp2p-crypto > /dev/null 2>1 && go get github.com/kr/pretty > /dev/null 2>1 \ - && go get github.com/kr/text > /dev/null 2>1 && go get gopkg.in/check.v1 > /dev/null 2>1 && bash scripts/install_build_tools.sh > /dev/null 2>1 && make > /dev/null 2>1 +#CRUN cd /go/src/github.com/harmony-one/harmony +RUN pwd +COPY harmony harmony +RUN go mod tidy +RUN go get github.com/pborman/uuid > /dev/null 2>1 +RUN go get github.com/rjeczalik/notify > /dev/null 2>1 +RUN go get github.com/cespare/cp > /dev/null 2>1 +RUN && go get github.com/libp2p/go-libp2p-crypto > /dev/null 2>1 +RUN && go get github.com/kr/pretty > /dev/null 2>1 +RUN && go get github.com/kr/text > /dev/null 2>1 +RUN && go get gopkg.in/check.v1 > /dev/null 2>1 +RUN && bash scripts/install_build_tools.sh > /dev/null 2>1 +RUN && make > /dev/null 2>1 RUN rm -rf harmony # Install testing tools @@ -36,7 +46,7 @@ WORKDIR $GOPATH/src/github.com/coinbase RUN git clone https://github.com/coinbase/rosetta-cli.git > /dev/null 2>1 RUN cd rosetta-cli && make install > /dev/null 2>1 -WORKDIR $GOPATH/src/github.com/harmony-one/harmony-test/localnet +WORKDIR $GOPATH/src/github.com/harmony-one/harmony/tests COPY scripts scripts COPY rpc_tests rpc_tests @@ -48,4 +58,4 @@ RUN python3 -m pip install -r requirements.txt --break-system-packages > /dev/nu RUN chmod +x $GOPATH/src/github.com/harmony-one/harmony-test/localnet/scripts/run.sh WORKDIR $GOPATH/src/github.com/harmony-one/harmony -ENTRYPOINT ["/go/src/github.com/harmony-one/harmony-test/localnet/scripts/run.sh"] +ENTRYPOINT ["/go/src/github.com/harmony-one/harmony/tests/scripts/run.sh"] From 49ead4936d3b8034f639fbc1719f5344a1ff92bf Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Fri, 28 Jun 2024 01:50:28 -0400 Subject: [PATCH 49/66] 1.21.11 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1a14a60c3b..d49484d812 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ os: linux dist: jammy language: go go: - - 1.19.5 + - 1.21.11 go_import_path: github.com/harmony-one/harmony cache: directories: From f204b08bf0da1af1531aaf466a68260d3053d26b Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Sat, 29 Jun 2024 20:25:15 -0400 Subject: [PATCH 50/66] Fixed rosetta --- scripts/travis_rosetta_checker.sh | 11 +++-------- scripts/travis_rpc_checker.sh | 3 --- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/scripts/travis_rosetta_checker.sh b/scripts/travis_rosetta_checker.sh index d2f98569f9..54554e8960 100644 --- a/scripts/travis_rosetta_checker.sh +++ b/scripts/travis_rosetta_checker.sh @@ -5,11 +5,6 @@ echo $TRAVIS_PULL_REQUEST_BRANCH DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo $DIR echo $GOPATH -cd $GOPATH/src/github.com/harmony-one/harmony-test -git fetch -git pull -git checkout $TRAVIS_PULL_REQUEST_BRANCH || true -git branch --show-current -cd localnet -docker build -t harmonyone/localnet-test . -docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -r \ No newline at end of file +pwd +docker build --progress=plain -t harmonyone/localnet-test -f Tests.Dockerfile . +docker run harmonyone/localnet-test -r \ No newline at end of file diff --git a/scripts/travis_rpc_checker.sh b/scripts/travis_rpc_checker.sh index 9bf0203d3d..e51fbbafd0 100755 --- a/scripts/travis_rpc_checker.sh +++ b/scripts/travis_rpc_checker.sh @@ -6,8 +6,5 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo $DIR echo $GOPATH pwd -#echo "$DIR/../:/go/src/github.com/harmony-one/harmony" docker build --progress=plain -t harmonyone/localnet-test -f Tests.Dockerfile . - -#docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -n docker run harmonyone/localnet-test -n \ No newline at end of file From b149cdb00834ada07cfeccaa22e5bd760e570660 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:46:46 -0400 Subject: [PATCH 51/66] Fixed rosetta --- Tests.Dockerfile | 12 +++++++----- p2p/host.go | 4 ++-- p2p/security/security_test.go | 8 ++++---- scripts/travis_rosetta_checker.sh | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Tests.Dockerfile b/Tests.Dockerfile index cb8a055eca..9c29100a32 100644 --- a/Tests.Dockerfile +++ b/Tests.Dockerfile @@ -22,6 +22,12 @@ RUN git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/ && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/bls > /dev/null 2>1 \ && git config --global --add safe.directory $GOPATH/src/github.com/harmony-one/mcl > /dev/null 2>1 +# Install testing tools +RUN curl -L -o /go/bin/hmy https://harmony.one/hmycli > /dev/null 2>1 && chmod +x /go/bin/hmy > /dev/null 2>1 + +RUN git clone https://github.com/coinbase/rosetta-cli.git > /dev/null 2>1 +RUN cd rosetta-cli && make install > /dev/null 2>1 + # Build to fetch all dependencies for faster test builds WORKDIR $GOPATH/src/github.com/harmony-one/harmony COPY . . @@ -40,16 +46,12 @@ RUN go mod tidy #RUN go get github.com/kr/text > /dev/null 2>1 #RUN go get gopkg.in/check.v1 > /dev/null 2>1 RUN bash scripts/install_build_tools.sh > /dev/null 2>1 -RUN make > /dev/null 2>1 +RUN make #RUN rm -rf harmony -# Install testing tools -RUN curl -L -o /go/bin/hmy https://harmony.one/hmycli > /dev/null 2>1 && chmod +x /go/bin/hmy > /dev/null 2>1 WORKDIR $GOPATH/src/github.com/coinbase -RUN git clone https://github.com/coinbase/rosetta-cli.git > /dev/null 2>1 -RUN cd rosetta-cli && make install > /dev/null 2>1 WORKDIR $GOPATH/src/github.com/harmony-one/harmony/tests diff --git a/p2p/host.go b/p2p/host.go index 7f6cfd7046..7de487d2cc 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -223,8 +223,8 @@ func NewHost(cfg HostConfig) (Host, error) { switch v { case "yamux": p2pHostConfig = append(p2pHostConfig, YamuxC()) - //case "mplex": - // p2pHostConfig = append(p2pHostConfig, MplexC()) + case "mplex": + //p2pHostConfig = append(p2pHostConfig, MplexC()) default: cancel() utils.Logger().Error(). diff --git a/p2p/security/security_test.go b/p2p/security/security_test.go index 3ebe589461..ca0857ec05 100644 --- a/p2p/security/security_test.go +++ b/p2p/security/security_test.go @@ -85,7 +85,7 @@ func TestManager_OnConnectCheck(t *testing.T) { h2, err := newPeer(GetFreePort(t)) assert.Nil(t, err) defer h2.Close() - err = h2.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Network().ListenAddresses()}) + err = h2.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Addrs()}) require.NoError(t, err) security.RangePeers(func(k string, peers []string) bool { @@ -96,7 +96,7 @@ func TestManager_OnConnectCheck(t *testing.T) { h3, err := newPeer(GetFreePort(t)) assert.Nil(t, err) defer h3.Close() - err = h3.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Network().ListenAddresses()}) + err = h3.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Addrs()}) assert.Nil(t, err) security.RangePeers(func(k string, peers []string) bool { require.Equal(t, 2, len(peers)) @@ -106,7 +106,7 @@ func TestManager_OnConnectCheck(t *testing.T) { h4, err := newPeer(GetFreePort(t)) assert.Nil(t, err) defer h4.Close() - err = h4.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Network().ListenAddresses()}) + err = h4.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Addrs()}) assert.Nil(t, err) security.RangePeers(func(k string, peers []string) bool { require.Equal(t, 2, len(peers)) @@ -143,7 +143,7 @@ func TestManager_OnDisconnectCheck(t *testing.T) { fakeHost.SetConnectCallback(OnConnectCheck) fakeHost.SetDisconnectCallback(OnDisconnectCheck) - err = h2.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Network().ListenAddresses()}) + err = h2.Connect(context.Background(), peer.AddrInfo{ID: h1.ID(), Addrs: h1.Addrs()}) assert.Nil(t, err) security.RangePeers(func(k string, peers []string) bool { diff --git a/scripts/travis_rosetta_checker.sh b/scripts/travis_rosetta_checker.sh index 54554e8960..ed1004c769 100644 --- a/scripts/travis_rosetta_checker.sh +++ b/scripts/travis_rosetta_checker.sh @@ -7,4 +7,4 @@ echo $DIR echo $GOPATH pwd docker build --progress=plain -t harmonyone/localnet-test -f Tests.Dockerfile . -docker run harmonyone/localnet-test -r \ No newline at end of file +docker run -v "$DIR/tmp_log:/go/src/github.com/harmony-one/harmony/tmp_log" harmonyone/localnet-test -r \ No newline at end of file From c643a3c1dbbac18198bf06c566fd210cc2df1e8a Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:15:18 -0400 Subject: [PATCH 52/66] Fixed bootstrap --- Makefile | 3 +++ cmd/bootnode/main.go | 2 +- p2p/discovery/option.go | 4 ++-- p2p/stream/common/requestmanager/requestmanager.go | 4 ++-- rpc/rpc.go | 4 ++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 93b7930c86..9fb5e844a0 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,9 @@ trace-pointer: debug: rm -rf .dht-127.0.0.1* + # uncomment the following lines to enable debug logging for libp2p, it produces a lot of logs, so disabled by default + #export GOLOG_LOG_LEVEL=debug + #export GOLOG_OUTPUT=stdout bash ./test/debug.sh debug-kill: diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index f6ab6481eb..d7a8e92d52 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -159,7 +159,7 @@ func main() { utils.FatalErrMsg(err, "cannot initialize network") } - fmt.Printf("bootnode BN_MA=%s", + fmt.Printf("bootnode BN_MA=%s\n", fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, host.GetID().String()), ) diff --git a/p2p/discovery/option.go b/p2p/discovery/option.go index fff8eea20f..64e4f7ade6 100644 --- a/p2p/discovery/option.go +++ b/p2p/discovery/option.go @@ -24,14 +24,14 @@ func (opt DHTConfig) GetLibp2pRawOptions() ([]libp2p_dht.Option, error) { bootOption, err := getBootstrapOption(opt.BootNodes) if err != nil { - return nil, err + return nil, errors.WithMessage(err, "failed to get bootstrap option") } opts = append(opts, bootOption) if opt.DataStoreFile != nil && len(*opt.DataStoreFile) != 0 { dsOption, err := getDataStoreOption(*opt.DataStoreFile) if err != nil { - return nil, err + return nil, errors.WithMessage(err, "failed to get data store option") } opts = append(opts, dsOption) } diff --git a/p2p/stream/common/requestmanager/requestmanager.go b/p2p/stream/common/requestmanager/requestmanager.go index 84d7210c7a..390d16bb94 100644 --- a/p2p/stream/common/requestmanager/requestmanager.go +++ b/p2p/stream/common/requestmanager/requestmanager.go @@ -362,11 +362,11 @@ func (rm *requestManager) refreshStreams() { added, removed := checkStreamUpdates(rm.streams, rm.sm.GetStreams()) for _, st := range added { - rm.logger.Info().Str("streamID", string(st.ID())).Msg("add new stream") + rm.logger.Info().Str("streamID", string(st.ID())).Msg("adding new stream") rm.addNewStream(st) } for _, st := range removed { - rm.logger.Info().Str("streamID", string(st.ID())).Msg("remove stream") + rm.logger.Info().Str("streamID", string(st.ID())).Msg("removing stream") rm.removeStream(st) } } diff --git a/rpc/rpc.go b/rpc/rpc.go index 96f042f6e7..15d7d93baf 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -256,7 +256,7 @@ func startWS(apis []rpc.API, rmf *rpc.RpcMethodFilter) (err error) { utils.Logger().Info(). Str("url", fmt.Sprintf("ws://%s", wsListener.Addr())). - Msg("WebSocket endpoint opened") + Msg("WebSocket WS endpoint opened") fmt.Printf("Started WS server at: %v\n", wsEndpoint) return nil } @@ -269,7 +269,7 @@ func startAuthWS(apis []rpc.API, rmf *rpc.RpcMethodFilter) (err error) { utils.Logger().Info(). Str("url", fmt.Sprintf("ws://%s", wsListener.Addr())). - Msg("WebSocket endpoint opened") + Msg("WebSocket Auth-WS endpoint opened") fmt.Printf("Started Auth-WS server at: %v\n", wsAuthEndpoint) return nil } From 9cf4cd2db6a971e0499ceb1c59b5ec20a8f24633 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 16 Jul 2024 09:32:28 -0400 Subject: [PATCH 53/66] Custom genesis generation for go@1.20+. --- core/genesis.go | 10 +++------- core/genesis/go19.go | 17 +++++++++++++++++ core/genesis/go20.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 core/genesis/go19.go create mode 100644 core/genesis/go20.go diff --git a/core/genesis.go b/core/genesis.go index e706235005..9656dd4a09 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -18,14 +18,12 @@ package core import ( "bytes" - "crypto/ecdsa" "encoding/hex" "encoding/json" "errors" "fmt" "math/big" "os" - "strings" "github.com/ethereum/go-ethereum/common" ethCommon "github.com/ethereum/go-ethereum/common" @@ -35,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" blockfactory "github.com/harmony-one/harmony/block/factory" + "github.com/harmony-one/harmony/core/genesis" "github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/staking/slash" @@ -124,11 +123,8 @@ func NewGenesisSpec(netType nodeconfig.NetworkType, shardID uint32) *Genesis { if netType != nodeconfig.Mainnet { gasLimit = params.TestGenesisGasLimit // Smart contract deployer account used to deploy initial smart contract - contractDeployerKey, _ := ecdsa.GenerateKey( - crypto.S256(), - strings.NewReader("Test contract key string stream that is fixed so that generated test key are deterministic every time"), - ) - contractDeployerAddress := crypto.PubkeyToAddress(contractDeployerKey.PublicKey) + + contractDeployerAddress := crypto.PubkeyToAddress(genesis.ContractDeployerKey.PublicKey) contractDeployerFunds := big.NewInt(ContractDeployerInitFund) contractDeployerFunds = contractDeployerFunds.Mul( contractDeployerFunds, big.NewInt(denominations.One), diff --git a/core/genesis/go19.go b/core/genesis/go19.go new file mode 100644 index 0000000000..7df2bcc8c6 --- /dev/null +++ b/core/genesis/go19.go @@ -0,0 +1,17 @@ +//go:build 1.19 +// +build 1.19 + +package genesis + +var ContractDeployerKey *ecdsa.PrivateKey + +func init() { + var err error + ContractDeployerKey, err = ecdsa.GenerateKey( + crypto.S256(), + strings.NewReader("Test contract key string stream that is fixed so that generated test key are deterministic every time"), + ) + if err != nil { + panic(err) + } +} diff --git a/core/genesis/go20.go b/core/genesis/go20.go new file mode 100644 index 0000000000..3b34fa23c2 --- /dev/null +++ b/core/genesis/go20.go @@ -0,0 +1,31 @@ +//go:build go1.20 +// +build go1.20 + +package genesis + +import ( + "crypto/ecdsa" + "math/big" + + "github.com/ethereum/go-ethereum/crypto" +) + +var ContractDeployerKey *ecdsa.PrivateKey + +func init() { + D := &big.Int{} + D.SetString("65737420636f6e7472616374206b657920737472696e672073747265616d2074", 16) + X := &big.Int{} + X.SetString("3d4fc035410b035f72da12df457ce17e255cede9fc9e72796ac3868ceb2ed226", 16) + Y := &big.Int{} + Y.SetString("808248810e75eb32859e46cdd8e541ed9f323bde6076d2ca6fd75d6cf0ffd089", 16) + + ContractDeployerKey = &ecdsa.PrivateKey{ + D: D, + PublicKey: ecdsa.PublicKey{ + Curve: crypto.S256(), + X: X, + Y: Y, + }, + } +} From 1939b71a8a6267c6447542edcbfd3e4be78721c7 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:39:31 -0400 Subject: [PATCH 54/66] Fixed 1.19 imports. --- core/genesis/go19.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/genesis/go19.go b/core/genesis/go19.go index 7df2bcc8c6..bba70e094e 100644 --- a/core/genesis/go19.go +++ b/core/genesis/go19.go @@ -3,6 +3,12 @@ package genesis +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/crypto" +) + var ContractDeployerKey *ecdsa.PrivateKey func init() { From 293309c7cd3f8bec03cc5e1e9fe028f7571b55a8 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 16 Jul 2024 20:55:16 -0400 Subject: [PATCH 55/66] Fixed 1.19 imports. --- core/genesis/go19.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/genesis/go19.go b/core/genesis/go19.go index bba70e094e..c1e5b92fd7 100644 --- a/core/genesis/go19.go +++ b/core/genesis/go19.go @@ -5,6 +5,7 @@ package genesis import ( "crypto/ecdsa" + "strings" "github.com/ethereum/go-ethereum/crypto" ) From 672a2fe60f1d6316f3505805e7d4a19d8fffa13e Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:43:13 -0400 Subject: [PATCH 56/66] Replaced 1.20 keys. --- core/genesis/go20.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/genesis/go20.go b/core/genesis/go20.go index 3b34fa23c2..a7fa3ea9c7 100644 --- a/core/genesis/go20.go +++ b/core/genesis/go20.go @@ -14,11 +14,11 @@ var ContractDeployerKey *ecdsa.PrivateKey func init() { D := &big.Int{} - D.SetString("65737420636f6e7472616374206b657920737472696e672073747265616d2074", 16) + D.SetString("7472616374206b65e45ffeb29e933944f5027ef139f124f430641487e70ea9a1", 16) X := &big.Int{} - X.SetString("3d4fc035410b035f72da12df457ce17e255cede9fc9e72796ac3868ceb2ed226", 16) + X.SetString("9b6b422147204489291d40321b154e5f3a07d341e8fa4db42a0eccb51c5cf768", 16) Y := &big.Int{} - Y.SetString("808248810e75eb32859e46cdd8e541ed9f323bde6076d2ca6fd75d6cf0ffd089", 16) + Y.SetString("308741f739674f61424fe8245ce2d9bf4914832deabddc2ba22de0f2c397a3ed", 16) ContractDeployerKey = &ecdsa.PrivateKey{ D: D, From 1412f475542976cd6b197ddd1e266f0bbc2e1518 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Thu, 18 Jul 2024 16:15:13 -0400 Subject: [PATCH 57/66] 100% coverage. --- core/genesis/key_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 core/genesis/key_test.go diff --git a/core/genesis/key_test.go b/core/genesis/key_test.go new file mode 100644 index 0000000000..15df4de07b --- /dev/null +++ b/core/genesis/key_test.go @@ -0,0 +1,11 @@ +package genesis + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestKeyExists(t *testing.T) { + require.NotEmpty(t, ContractDeployerKey) +} From 963d5198dfa3cbb115764c819804b6521e0f18d3 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:48:21 -0400 Subject: [PATCH 58/66] Fixed trailing zeroes. --- go.mod | 4 ++-- go.sum | 4 ++-- staking/availability/measure_test.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index eaaf133588..f41a03cdd3 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,8 @@ require ( github.com/ledgerwatch/log/v3 v3.8.0 github.com/olekukonko/tablewriter v0.0.5 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 + golang.org/x/term v0.20.0 + golang.org/x/text v0.15.0 ) require ( @@ -283,8 +285,6 @@ require ( go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect gonum.org/v1/gonum v0.13.0 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 21b4783240..68b234363a 100644 --- a/go.sum +++ b/go.sum @@ -2183,8 +2183,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/staking/availability/measure_test.go b/staking/availability/measure_test.go index b3a26d8172..786d59ec04 100644 --- a/staking/availability/measure_test.go +++ b/staking/availability/measure_test.go @@ -758,7 +758,7 @@ func TestUpdateMaxCommissionFee(t *testing.T) { err := UpdateMaxCommissionFee(true, v1, common.Address{}, numeric.MustNewDecFromStr("0.6")) require.NoError(t, err) - require.Equal(t, "1.000000000000000000", v1.v.Commission.CommissionRates.MaxRate.String()) + require.Equal(t, "1", v1.v.Commission.CommissionRates.MaxRate.String()) }) t.Run("0.07 + 0.5 = 0.57", func(t *testing.T) { @@ -776,7 +776,7 @@ func TestUpdateMaxCommissionFee(t *testing.T) { } err := UpdateMaxCommissionFee(true, v2, common.Address{}, numeric.MustNewDecFromStr("0.07")) require.NoError(t, err) - require.Equal(t, "0.570000000000000000", v2.v.Commission.CommissionRates.MaxRate.String()) + require.Equal(t, "0.57", v2.v.Commission.CommissionRates.MaxRate.String()) }) t.Run("error", func(t *testing.T) { From 2bd71bf6656d37140f13ff38a8b214b090d3f173 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:43:00 -0400 Subject: [PATCH 59/66] Rebased & Fixed protobuf usage. --- api/proto/message/harmonymessage.pb.go | 138 ++++++++++++++----------- 1 file changed, 77 insertions(+), 61 deletions(-) diff --git a/api/proto/message/harmonymessage.pb.go b/api/proto/message/harmonymessage.pb.go index ac2bdd3164..cf315d5042 100644 --- a/api/proto/message/harmonymessage.pb.go +++ b/api/proto/message/harmonymessage.pb.go @@ -852,7 +852,7 @@ type LastSignPowerRequest struct { func (x *LastSignPowerRequest) Reset() { *x = LastSignPowerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_message_proto_msgTypes[7] + mi := &file_harmonymessage_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -865,7 +865,7 @@ func (x *LastSignPowerRequest) String() string { func (*LastSignPowerRequest) ProtoMessage() {} func (x *LastSignPowerRequest) ProtoReflect() protoreflect.Message { - mi := &file_message_proto_msgTypes[7] + mi := &file_harmonymessage_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -878,7 +878,7 @@ func (x *LastSignPowerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LastSignPowerRequest.ProtoReflect.Descriptor instead. func (*LastSignPowerRequest) Descriptor() ([]byte, []int) { - return file_message_proto_rawDescGZIP(), []int{7} + return file_harmonymessage_proto_rawDescGZIP(), []int{7} } func (x *LastSignPowerRequest) GetPrepare() int64 { @@ -1066,7 +1066,7 @@ var File_harmonymessage_proto protoreflect.FileDescriptor var file_harmonymessage_proto_rawDesc = []byte{ 0x0a, 0x14, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xf3, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc3, 0x04, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, @@ -1097,7 +1097,12 @@ var file_harmonymessage_proto_rawDesc = []byte{ 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x0e, 0x6c, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xd9, 0x01, 0x0a, + 0x74, 0x12, 0x4e, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x70, + 0x6f, 0x77, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x72, + 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x61, 0x73, 0x74, + 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x48, 0x00, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, 0x77, 0x65, + 0x72, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xd9, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, @@ -1161,59 +1166,70 @@ var file_harmonymessage_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x22, 0xad, 0x03, 0x0a, 0x11, 0x56, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, 0x65, 0x77, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, - 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, - 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x25, 0x0a, 0x0e, - 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, 0x5f, 0x73, 0x69, - 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, 0x53, - 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x32, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x32, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, - 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x32, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x32, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x1d, - 0x0a, 0x0a, 0x6d, 0x33, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x33, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x12, 0x1b, 0x0a, - 0x09, 0x6d, 0x33, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x08, 0x6d, 0x33, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, - 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x2a, 0x50, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x10, 0x00, 0x12, - 0x0f, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, - 0x12, 0x0d, 0x0a, 0x05, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x12, - 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, - 0x54, 0x10, 0x03, 0x2a, 0xd1, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x16, 0x4e, 0x45, 0x57, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x42, - 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x1a, - 0x02, 0x08, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x10, - 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x02, 0x12, 0x0c, - 0x0a, 0x08, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, - 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x4d, - 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x49, 0x45, 0x57, 0x43, - 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x45, 0x57, 0x56, 0x49, - 0x45, 0x57, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0a, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x5f, 0x49, 0x4e, - 0x49, 0x54, 0x10, 0x0a, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x44, 0x52, 0x41, 0x4e, - 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0b, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x17, - 0x0a, 0x0f, 0x4c, 0x4f, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, - 0x54, 0x10, 0x0c, 0x1a, 0x02, 0x08, 0x01, 0x32, 0x4f, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x12, 0x17, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x68, - 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x13, 0x5a, 0x11, 0x2e, 0x2f, 0x3b, 0x68, - 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x14, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x6f, + 0x77, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x70, 0x72, 0x65, + 0x70, 0x61, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x49, 0x64, 0x22, 0xad, 0x03, 0x0a, 0x11, 0x56, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x76, 0x69, + 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x69, 0x65, + 0x77, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, + 0x25, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x69, 0x65, 0x77, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x65, 0x77, 0x69, 0x64, + 0x5f, 0x73, 0x69, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x69, 0x65, 0x77, + 0x69, 0x64, 0x53, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x32, 0x5f, 0x61, 0x67, 0x67, 0x73, + 0x69, 0x67, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x32, 0x41, 0x67, 0x67, + 0x73, 0x69, 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x32, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, + 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x32, 0x42, 0x69, 0x74, 0x6d, 0x61, + 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x33, 0x5f, 0x61, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x33, 0x41, 0x67, 0x67, 0x73, 0x69, 0x67, 0x73, + 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x33, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x33, 0x42, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x25, 0x0a, + 0x0e, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x2a, 0x50, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, + 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, + 0x02, 0x08, 0x01, 0x12, 0x0d, 0x0a, 0x05, 0x44, 0x52, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x02, + 0x08, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x55, 0x50, + 0x50, 0x4f, 0x52, 0x54, 0x10, 0x03, 0x2a, 0xe6, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x16, 0x4e, 0x45, 0x57, 0x4e, 0x4f, 0x44, + 0x45, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4b, 0x49, 0x4e, 0x47, + 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x4e, 0x4f, 0x55, 0x4e, + 0x43, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, + 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x44, 0x10, 0x03, 0x12, + 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x43, + 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x49, + 0x45, 0x57, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x45, + 0x57, 0x56, 0x49, 0x45, 0x57, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0a, 0x44, 0x52, 0x41, 0x4e, 0x44, + 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x0a, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x44, + 0x52, 0x41, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0b, 0x1a, 0x02, 0x08, + 0x01, 0x12, 0x17, 0x0a, 0x0f, 0x4c, 0x4f, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x51, + 0x55, 0x45, 0x53, 0x54, 0x10, 0x0c, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x41, + 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x10, 0x0d, 0x32, + 0x4f, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x3e, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x17, 0x2e, 0x68, 0x61, + 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x13, 0x5a, 0x11, 0x2e, 0x2f, 0x3b, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1241,7 +1257,7 @@ var file_harmonymessage_proto_goTypes = []interface{}{ (*StakingRequest)(nil), // 7: harmonymessage.StakingRequest (*ConsensusRequest)(nil), // 8: harmonymessage.ConsensusRequest (*DrandRequest)(nil), // 9: harmonymessage.DrandRequest - (*LastSignPowerRequest)(nil), // 10: message.LastSignPowerRequest + (*LastSignPowerRequest)(nil), // 10: harmonymessage.LastSignPowerRequest (*ViewChangeRequest)(nil), // 11: harmonymessage.ViewChangeRequest } var file_harmonymessage_proto_depIdxs = []int32{ @@ -1252,7 +1268,7 @@ var file_harmonymessage_proto_depIdxs = []int32{ 9, // 4: harmonymessage.Message.drand:type_name -> harmonymessage.DrandRequest 11, // 5: harmonymessage.Message.viewchange:type_name -> harmonymessage.ViewChangeRequest 6, // 6: harmonymessage.Message.lottery_request:type_name -> harmonymessage.LotteryRequest - 10, // 7: message.Message.last_sign_power:type_name -> message.LastSignPowerRequest + 10, // 7: harmonymessage.Message.last_sign_power:type_name -> harmonymessage.LastSignPowerRequest 0, // 8: harmonymessage.Response.service_type:type_name -> harmonymessage.ServiceType 1, // 9: harmonymessage.Response.type:type_name -> harmonymessage.MessageType 5, // 10: harmonymessage.Response.lottery_response:type_name -> harmonymessage.LotteryResponse @@ -1368,7 +1384,7 @@ func file_harmonymessage_proto_init() { return nil } } - file_message_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_harmonymessage_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ViewChangeRequest); i { case 0: return &v.state From edceca8f2d40c24ee5fa9f0f167a281e269102ac Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:14:57 -0400 Subject: [PATCH 60/66] PrintPeers --- node/node_handler.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/node/node_handler.go b/node/node_handler.go index 7aa87100bb..373c9cad35 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -418,6 +418,7 @@ func IsRunningBeaconChain(c *consensus.Consensus) bool { // BootstrapConsensus is a goroutine to check number of peers and start the consensus func (node *Node) BootstrapConsensus() error { + go node.PrintPeers() ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() min := node.Consensus.MinPeers @@ -452,3 +453,12 @@ func (node *Node) BootstrapConsensus() error { return nil } } + +func (node *Node) PrintPeers() { + for { + <-time.After(5 * time.Second) + known := node.host.GetPeerCount() + connected := len(node.host.Network().Peers()) + fmt.Printf("connected %d, known %d\n", connected, known) + } +} From c69df179bb658291e4a71c532a011a446d457553 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:15:48 -0400 Subject: [PATCH 61/66] No security --- p2p/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p2p/host.go b/p2p/host.go index 7de487d2cc..083ccdf739 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -210,7 +210,7 @@ func NewHost(cfg HostConfig) (Host, error) { } // Set host security - if cfg.NoTransportSecurity { + if cfg.NoTransportSecurity || true { p2pHostConfig = append(p2pHostConfig, libp2p.Security(insecure.ID, insecure.NewWithIdentity)) } else { p2pHostConfig = append(p2pHostConfig, NoiseC(), TlsC()) From 73df3bd049f7789feea2038cca65e881aba297d3 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:35:34 -0400 Subject: [PATCH 62/66] Mplex compability. --- core/blockchain_impl.go | 3 +++ go.mod | 2 ++ go.sum | 4 ++++ p2p/host.go | 49 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/core/blockchain_impl.go b/core/blockchain_impl.go index a065ecfd6d..8dbc57766d 100644 --- a/core/blockchain_impl.go +++ b/core/blockchain_impl.go @@ -1711,6 +1711,9 @@ func (bc *BlockChainImpl) insertChain(chain types.Blocks, verifyHeaders bool) (i if len(chain) == 0 { return 0, nil, nil, ErrEmptyChain } + if first := chain[0]; true { + fmt.Println(utils.GetPort(), first.ShardID(), first.Epoch().Uint64(), first.NumberU64()) + } // Do a sanity check that the provided chain is actually ordered and linked for i := 1; i < len(chain); i++ { if chain[i].NumberU64() != chain[i-1].NumberU64()+1 || chain[i].ParentHash() != chain[i-1].Hash() { diff --git a/go.mod b/go.mod index f41a03cdd3..0796e6b7f5 100644 --- a/go.mod +++ b/go.mod @@ -72,6 +72,7 @@ require ( 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/libp2p/go-libp2p-mplex v0.9.0 github.com/olekukonko/tablewriter v0.0.5 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/term v0.20.0 @@ -183,6 +184,7 @@ require ( github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect github.com/libp2p/go-libp2p-record v0.2.0 // indirect github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect + github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-nat v0.2.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect diff --git a/go.sum b/go.sum index 68b234363a..f0c8e42e0e 100644 --- a/go.sum +++ b/go.sum @@ -878,6 +878,8 @@ github.com/libp2p/go-libp2p-kad-dht v0.25.2 h1:FOIk9gHoe4YRWXTu8SY9Z1d0RILol0Trt github.com/libp2p/go-libp2p-kad-dht v0.25.2/go.mod h1:6za56ncRHYXX4Nc2vn8z7CZK0P4QiMcrn77acKLM2Oo= github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0= github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0= +github.com/libp2p/go-libp2p-mplex v0.9.0 h1:R58pDRAmuBXkYugbSSXR9wrTX3+1pFM1xP2bLuodIq8= +github.com/libp2p/go-libp2p-mplex v0.9.0/go.mod h1:ro1i4kuwiFT+uMPbIDIFkcLs1KRbNp0QwnUXM+P64Og= github.com/libp2p/go-libp2p-pubsub v0.11.0 h1:+JvS8Kty0OiyUiN0i8H5JbaCgjnJTRnTHe4rU88dLFc= github.com/libp2p/go-libp2p-pubsub v0.11.0/go.mod h1:QEb+hEV9WL9wCiUAnpY29FZR6W3zK8qYlaml8R4q6gQ= github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= @@ -886,6 +888,8 @@ github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsa github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= +github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= diff --git a/p2p/host.go b/p2p/host.go index 083ccdf739..d994c1e245 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -40,6 +40,8 @@ import ( yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux" noise "github.com/libp2p/go-libp2p/p2p/security/noise" tls "github.com/libp2p/go-libp2p/p2p/security/tls" + //mplex "github.com/libp2p/go-mplex" + mplex "github.com/libp2p/go-libp2p-mplex" madns "github.com/multiformats/go-multiaddr-dns" ) @@ -222,9 +224,9 @@ func NewHost(cfg HostConfig) (Host, error) { v = strings.ToLower(strings.TrimSpace(v)) switch v { case "yamux": - p2pHostConfig = append(p2pHostConfig, YamuxC()) + //p2pHostConfig = append(p2pHostConfig, YamuxC()) case "mplex": - //p2pHostConfig = append(p2pHostConfig, MplexC()) + p2pHostConfig = append(p2pHostConfig, MplexC()) default: cancel() utils.Logger().Error(). @@ -352,9 +354,9 @@ func YamuxC() libp2p.Option { return libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport) } -//func MplexC() libp2p.Option { -// return libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport) -//} +func MplexC() libp2p.Option { + return libp2p.Muxer("/mplex/0.7.0", mplex.DefaultTransport) +} func NoiseC() libp2p.Option { return libp2p.Security(noise.ID, noise.New) @@ -364,6 +366,43 @@ func TlsC() libp2p.Option { return libp2p.Security(tls.ID, tls.New) } +//var _ libp2p_network.MuxedConn = &Mplex{} +// +//type Mplex struct { +// m *mplex.Multiplex +//} +// +//func (m *Mplex) Close() error { +// return m.m.Close() +//} +// +//func (m *Mplex) IsClosed() bool { +// return m.m.IsClosed() +//} +// +//func (m *Mplex) OpenStream(ctx context.Context) (libp2p_network.MuxedStream, error) { +// fmt.Println("Open stream") +// return m.m.NewStream(ctx) +//} +// +//func (m *Mplex) AcceptStream() (libp2p_network.MuxedStream, error) { +// fmt.Println("accept stream") +// return m.m.NewStream(context.Background()) +//} +// +//func (m DefaultMplex) NewConn(nc net.Conn, isServer bool, scope libp2p_network.PeerScope) (libp2p_network.MuxedConn, error) { +// rs, err := mplex.NewMultiplex(nc, isServer, scope) +// if err != nil { +// return nil, err +// } +// return &Mplex{ +// m: rs, +// }, nil +//} +// +//type DefaultMplex struct { +//} + // connectionManager creates a new connection manager and configures libp2p to use the // given connection manager. // lo and hi are watermarks governing the number of connections that'll be maintained. From 5d869db3824bc2988081c10787ab3f3cd39a52d7 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:26:09 -0400 Subject: [PATCH 63/66] Mplex 6&0 compability. --- p2p/host.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/p2p/host.go b/p2p/host.go index d994c1e245..ec1cb241e4 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -226,7 +226,7 @@ func NewHost(cfg HostConfig) (Host, error) { case "yamux": //p2pHostConfig = append(p2pHostConfig, YamuxC()) case "mplex": - p2pHostConfig = append(p2pHostConfig, MplexC()) + p2pHostConfig = append(p2pHostConfig, MplexC6(), MplexC0()) default: cancel() utils.Logger().Error(). @@ -354,7 +354,11 @@ func YamuxC() libp2p.Option { return libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport) } -func MplexC() libp2p.Option { +func MplexC6() libp2p.Option { + return libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport) +} + +func MplexC0() libp2p.Option { return libp2p.Muxer("/mplex/0.7.0", mplex.DefaultTransport) } From 92af75941b2fa2fe02a526b25ce982b6c9e678b2 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 24 Jul 2024 09:23:03 -0400 Subject: [PATCH 64/66] Fixed failing tests. --- api/service/legacysync/epoch_syncing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/service/legacysync/epoch_syncing.go b/api/service/legacysync/epoch_syncing.go index 09c4a62da8..54bf7b486d 100644 --- a/api/service/legacysync/epoch_syncing.go +++ b/api/service/legacysync/epoch_syncing.go @@ -204,7 +204,7 @@ func processWithPayload(payload [][]byte, bc core.BlockChain) error { for idx, blockBytes := range payload { block, err := RlpDecodeBlockOrBlockWithSig(blockBytes) if err != nil { - return errors.Wrap(err, "failed decode") + return errors.WithMessagef(err, "failed decode %x", blockBytes) } if !block.IsLastBlockInEpoch() { From 45c0539901974c2200d6411433b1cf65956ab21d Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:01:30 -0400 Subject: [PATCH 65/66] Fixed failing tests. --- internal/chain/sig.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/chain/sig.go b/internal/chain/sig.go index 23b51d5f1b..14d2b00132 100644 --- a/internal/chain/sig.go +++ b/internal/chain/sig.go @@ -1,12 +1,10 @@ package chain import ( - "errors" - bls_core "github.com/harmony-one/bls/ffi/go/bls" - "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/internal/utils" + "github.com/pkg/errors" ) // ReadSignatureBitmapByPublicKeys read the payload of signature and bitmap based on public keys @@ -42,7 +40,7 @@ func DecodeSigBitmap(sigBytes bls.SerializedSignature, bitmap []byte, pubKeys [] } mask := bls.NewMask(pubKeys) if err := mask.SetMask(bitmap); err != nil { - utils.Logger().Warn().Err(err).Msg("mask.SetMask failed") + utils.Logger().Warn().Err(errors.WithStack(err)).Msg("mask.SetMask failed") return nil, nil, errors.New("mask.SetMask failed") } return &aggSig, mask, nil From 74f8a298a0fd7e000b3d7626a79cd5ea40fc05ca Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:16:08 -0400 Subject: [PATCH 66/66] Added logs. --- internal/chain/sig.go | 4 ++-- internal/chain/sig_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 internal/chain/sig_test.go diff --git a/internal/chain/sig.go b/internal/chain/sig.go index 14d2b00132..129b53d411 100644 --- a/internal/chain/sig.go +++ b/internal/chain/sig.go @@ -40,8 +40,8 @@ func DecodeSigBitmap(sigBytes bls.SerializedSignature, bitmap []byte, pubKeys [] } mask := bls.NewMask(pubKeys) if err := mask.SetMask(bitmap); err != nil { - utils.Logger().Warn().Err(errors.WithStack(err)).Msg("mask.SetMask failed") - return nil, nil, errors.New("mask.SetMask failed") + utils.Logger().Warn().Err(errors.WithStack(err)).Msgf("mask.SetMask failed %+v", err) + return nil, nil, errors.Errorf("mask.SetMask failed %+v", err) } return &aggSig, mask, nil } diff --git a/internal/chain/sig_test.go b/internal/chain/sig_test.go new file mode 100644 index 0000000000..1c5097f755 --- /dev/null +++ b/internal/chain/sig_test.go @@ -0,0 +1,25 @@ +package chain + +import ( + "fmt" + "testing" + + bls_core "github.com/harmony-one/bls/ffi/go/bls" + "github.com/harmony-one/harmony/crypto/bls" +) + +func TestDecodeSigBitmap(t *testing.T) { + + aggSig := bls_core.Sign{} + rs := aggSig.Serialize() + var sigBytes bls.SerializedSignature + copy(sigBytes[:], rs[:]) + // gen pub keys + pub := bls.WrapperFromPrivateKey(bls.RandPrivateKey()) + + pubKeys := []bls.PublicKeyWrapper{*pub.Pub} + + _, _, err := DecodeSigBitmap(sigBytes, nil, pubKeys) + fmt.Println(err.Error()) + //require.NoError(t, err) +}