Merge branch 'master' into blacklist

pull/2172/head
Daniel Van Der Maden 5 years ago committed by GitHub
commit 770c2139bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      cmd/harmony/main.go
  2. 21
      go.mod
  3. 6
      internal/hmyapi/apiv1/blockchain.go
  4. 113
      internal/hmyapi/apiv2/blockchain.go
  5. 18
      internal/hmyapi/apiv2/transactionpool.go
  6. 10
      internal/hmyapi/backend.go
  7. 64
      internal/utils/gomock_reflect_069400606/prog.go
  8. 64
      internal/utils/gomock_reflect_579506979/prog.go
  9. 6
      node/rpc.go
  10. 95
      p2p/host/hostv2/hostv2.go
  11. 87
      p2p/host/hostv2/hostv2_mock_for_test.go
  12. 261
      p2p/host/hostv2/hostv2_test.go
  13. 8
      scripts/go_executable_build.sh
  14. 1
      scripts/list_harmony_go_files.sh
  15. 9
      scripts/node.sh

@ -37,6 +37,9 @@ import (
"github.com/harmony-one/harmony/p2p/p2pimpl"
p2putils "github.com/harmony-one/harmony/p2p/utils"
"github.com/harmony-one/harmony/shard"
golog "github.com/ipfs/go-log"
gologging "github.com/whyrusleeping/go-logging"
)
// Version string variables
@ -104,8 +107,12 @@ var (
devnetShardSize = flag.Int("dn_shard_size", 10, "number of nodes per shard for -network_type=devnet (default 10)")
devnetHarmonySize = flag.Int("dn_hmy_size", -1, "number of Harmony-operated nodes per shard for -network_type=devnet; negative (default) means equal to -dn_shard_size")
// logConn logs incoming/outgoing connections
logConn = flag.Bool("log_conn", false, "log incoming/outgoing connections")
keystoreDir = flag.String("keystore", hmykey.DefaultKeyStoreDir, "The default keystore directory")
logConn = flag.Bool("log_conn", false, "log incoming/outgoing connections")
keystoreDir = flag.String("keystore", hmykey.DefaultKeyStoreDir, "The default keystore directory")
// Use a separate log file to log libp2p traces
logP2P = flag.Bool("log_p2p", false, "log libp2p debug info")
initialAccount = &genesis.DeployAccount{}
// logging verbosity
verbosity = flag.Int("verbosity", 5, "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail (default: 5)")
@ -580,6 +587,19 @@ func main() {
if *enableMemProfiling {
memprofiling.GetMemProfiling().Start()
}
if *logP2P {
f, err := os.OpenFile(path.Join(*logFolder, "libp2p.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to open libp2p.log. %v\n", err)
} else {
defer f.Close()
backend1 := gologging.NewLogBackend(f, "", 0)
gologging.SetBackend(backend1)
golog.SetAllLoggers(gologging.DEBUG) // Change to DEBUG for extra info
}
}
go currentNode.SupportSyncing()
currentNode.ServiceManagerSetup()

@ -22,16 +22,16 @@ require (
github.com/gorilla/handlers v1.4.0
github.com/gorilla/mux v1.7.2
github.com/harmony-ek/gencodec v0.0.0-20190215044613-e6740dbdd846
github.com/harmony-one/bls v0.0.5
github.com/harmony-one/bls v0.0.6
github.com/harmony-one/taggedrlp v0.1.4
github.com/harmony-one/vdf v0.0.0-20190924175951-620379da8849
github.com/hashicorp/golang-lru v0.5.1
github.com/hashicorp/golang-lru v0.5.3
github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365
github.com/ipfs/go-ds-badger v0.0.7
github.com/ipfs/go-log v0.0.1
github.com/karalabe/hid v1.0.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/libp2p/go-libp2p v0.5.0
github.com/libp2p/go-libp2p v0.3.1
github.com/libp2p/go-libp2p-core v0.3.0
github.com/libp2p/go-libp2p-crypto v0.1.0
github.com/libp2p/go-libp2p-discovery v0.2.0
@ -39,10 +39,12 @@ require (
github.com/libp2p/go-libp2p-kad-dht v0.2.0
github.com/libp2p/go-libp2p-net v0.1.0
github.com/libp2p/go-libp2p-peer v0.2.0
github.com/libp2p/go-libp2p-peerstore v0.1.4
github.com/libp2p/go-libp2p-pubsub v0.1.1
github.com/libp2p/go-libp2p-peerstore v0.1.3
github.com/libp2p/go-libp2p-pubsub v0.2.5
github.com/libp2p/go-ws-transport v0.1.1 // indirect
github.com/multiformats/go-multiaddr v0.2.0
github.com/multiformats/go-multiaddr-net v0.1.1
github.com/multiformats/go-multiaddr-dns v0.1.1 // indirect
github.com/multiformats/go-multiaddr-net v0.1.0
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.8.1
@ -56,9 +58,12 @@ require (
github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965
github.com/whyrusleeping/go-logging v0.0.1
github.com/uber/jaeger-client-go v2.20.1+incompatible // indirect
github.com/uber/jaeger-lib v2.2.0+incompatible // indirect
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc
go.uber.org/atomic v1.5.1 // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/lint v0.0.0-20190409202823-959b441ac422
golang.org/x/lint v0.0.0-20190930215403-16217165b5de
golang.org/x/tools v0.0.0-20191113232020-e2727e816f5a
google.golang.org/grpc v1.22.0
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15

@ -498,11 +498,11 @@ var (
// GetMedianRawStakeSnapshot returns the raw median stake, only meant to be called on beaconchain
// explorer node
func (s *PublicBlockChainAPI) GetMedianRawStakeSnapshot() (uint64, error) {
func (s *PublicBlockChainAPI) GetMedianRawStakeSnapshot() (*big.Int, error) {
if s.b.IsBeaconChainExplorerNode() {
return s.GetMedianRawStakeSnapshot()
return s.b.GetMedianRawStakeSnapshot(), nil
}
return 0, errNotExplorerNode
return nil, errNotExplorerNode
}
// GetAllValidatorAddresses returns all validator addresses.

@ -49,50 +49,20 @@ type BlockArgs struct {
InclStaking bool `json:"inclStaking"`
}
// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, blockNr)
// GetBlockByNumber returns the requested block. When fullTx in blockArgs is true all transactions in the block are returned in full detail,
// otherwise only the transaction hash is returned. When withSigners in BlocksArgs is true it shows block signers for this block in list of one addresses.
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr uint64, blockArgs BlockArgs) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr))
blockArgs.InclTx = true
if block != nil {
blockArgs := BlockArgs{WithSigners: false, InclTx: true, FullTx: fullTx, InclStaking: true}
response, err := RPCMarshalBlock(block, blockArgs)
if err == nil && blockNr == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
response[field] = nil
if blockArgs.WithSigners {
blockArgs.Signers, err = s.GetBlockSigners(ctx, blockNr)
if err != nil {
return nil, err
}
}
return response, err
}
return nil, err
}
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.GetBlock(ctx, blockHash)
if block != nil {
blockArgs := BlockArgs{WithSigners: false, InclTx: true, FullTx: fullTx, InclStaking: true}
return RPCMarshalBlock(block, blockArgs)
}
return nil, err
}
// GetBlockByNumberNew returns the requested block. When blockNr is -1 the chain head is returned. When fullTx in blockArgs is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned. When withSigners in BlocksArgs is true
// it shows block signers for this block in list of one addresses.
func (s *PublicBlockChainAPI) GetBlockByNumberNew(ctx context.Context, blockNr rpc.BlockNumber, blockArgs BlockArgs) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, blockNr)
blockArgs.InclTx = true
if blockArgs.WithSigners {
blockArgs.Signers, err = s.GetBlockSigners(ctx, blockNr)
if err != nil {
return nil, err
}
}
if block != nil {
response, err := RPCMarshalBlock(block, blockArgs)
if err == nil && blockNr == rpc.PendingBlockNumber {
if err == nil && rpc.BlockNumber(blockNr) == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
response[field] = nil
@ -103,39 +73,39 @@ func (s *PublicBlockChainAPI) GetBlockByNumberNew(ctx context.Context, blockNr r
return nil, err
}
// GetBlockByHashNew returns the requested block. When fullTx in blockArgs is true all transactions in the block are returned in full
// GetBlockByHash returns the requested block. When fullTx in blockArgs is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned. When withSigners in BlocksArgs is true
// it shows block signers for this block in list of one addresses.
func (s *PublicBlockChainAPI) GetBlockByHashNew(ctx context.Context, blockHash common.Hash, blockArgs BlockArgs) (map[string]interface{}, error) {
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, blockArgs BlockArgs) (map[string]interface{}, error) {
block, err := s.b.GetBlock(ctx, blockHash)
blockArgs.InclTx = true
if blockArgs.WithSigners {
blockArgs.Signers, err = s.GetBlockSigners(ctx, rpc.BlockNumber(block.NumberU64()))
if err != nil {
return nil, err
}
}
if block != nil {
if blockArgs.WithSigners {
blockArgs.Signers, err = s.GetBlockSigners(ctx, block.NumberU64())
if err != nil {
return nil, err
}
}
return RPCMarshalBlock(block, blockArgs)
}
return nil, err
}
// GetBlocks method returns blocks in range blockStart, blockEnd just like GetBlockByNumber but all at once.
func (s *PublicBlockChainAPI) GetBlocks(ctx context.Context, blockStart rpc.BlockNumber, blockEnd rpc.BlockNumber, blockArgs BlockArgs) ([]map[string]interface{}, error) {
func (s *PublicBlockChainAPI) GetBlocks(ctx context.Context, blockStart, blockEnd uint64, blockArgs BlockArgs) ([]map[string]interface{}, error) {
result := make([]map[string]interface{}, 0)
for i := blockStart; i <= blockEnd; i++ {
block, err := s.b.BlockByNumber(ctx, i)
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(i))
blockArgs.InclTx = true
if blockArgs.WithSigners {
blockArgs.Signers, err = s.GetBlockSigners(ctx, rpc.BlockNumber(i))
blockArgs.Signers, err = s.GetBlockSigners(ctx, i)
if err != nil {
return nil, err
}
}
if block != nil {
rpcBlock, err := RPCMarshalBlock(block, blockArgs)
if err == nil && i == rpc.PendingBlockNumber {
if err == nil && rpc.BlockNumber(i) == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
rpcBlock[field] = nil
@ -177,15 +147,15 @@ func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (m
}
// GetBlockSigners returns signers for a particular block.
func (s *PublicBlockChainAPI) GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) ([]string, error) {
if uint64(blockNr) == 0 || uint64(blockNr) >= uint64(s.BlockNumber()) {
func (s *PublicBlockChainAPI) GetBlockSigners(ctx context.Context, blockNr uint64) ([]string, error) {
if blockNr == 0 || blockNr >= uint64(s.BlockNumber()) {
return make([]string, 0), nil
}
block, err := s.b.BlockByNumber(ctx, blockNr)
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr))
if err != nil {
return nil, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, blockNr+1)
blockWithSigners, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr+1))
if err != nil {
return nil, err
}
@ -225,15 +195,15 @@ func (s *PublicBlockChainAPI) GetBlockSigners(ctx context.Context, blockNr rpc.B
}
// IsBlockSigner returns true if validator with address signed blockNr block.
func (s *PublicBlockChainAPI) IsBlockSigner(ctx context.Context, blockNr rpc.BlockNumber, address string) (bool, error) {
if uint64(blockNr) == 0 || uint64(blockNr) >= uint64(s.BlockNumber()) {
func (s *PublicBlockChainAPI) IsBlockSigner(ctx context.Context, blockNr uint64, address string) (bool, error) {
if blockNr == 0 || blockNr >= uint64(s.BlockNumber()) {
return false, nil
}
block, err := s.b.BlockByNumber(ctx, blockNr)
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr))
if err != nil {
return false, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, blockNr+1)
blockWithSigners, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr+1))
if err != nil {
return false, err
}
@ -280,7 +250,7 @@ func (s *PublicBlockChainAPI) GetSignedBlocks(ctx context.Context, address strin
lastBlock = blockHeight - defaultBlocksPeriod + 1
}
for i := lastBlock; i <= blockHeight; i++ {
signed, err := s.IsBlockSigner(ctx, rpc.BlockNumber(i), address)
signed, err := s.IsBlockSigner(ctx, i, address)
if err == nil && signed {
totalSigned++
}
@ -329,9 +299,9 @@ func (s *PublicBlockChainAPI) GetShardID(ctx context.Context) (int, error) {
}
// GetCode returns the code stored at the given address in the state for the given block number.
func (s *PublicBlockChainAPI) GetCode(ctx context.Context, addr string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
func (s *PublicBlockChainAPI) GetCode(ctx context.Context, addr string, blockNr uint64) (hexutil.Bytes, error) {
address := internal_common.ParseAddr(addr)
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.BlockNumber(blockNr))
if state == nil || err != nil {
return nil, err
}
@ -342,9 +312,9 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, addr string, blockNr
// GetStorageAt returns the storage from the state at the given address, key and
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed.
func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, addr string, key string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, addr string, key string, blockNr uint64) (hexutil.Bytes, error) {
address := internal_common.ParseAddr(addr)
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.BlockNumber(blockNr))
if state == nil || err != nil {
return nil, err
}
@ -352,11 +322,8 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, addr string, key
return res[:], state.Error()
}
// GetBalance returns the amount of Nano for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.
func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address string, blockNr rpc.BlockNumber) (*big.Int, error) {
// TODO: currently only get latest balance. Will add complete logic later.
// GetBalance returns the amount of Nano for the given address in the state.
func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address string) (*big.Int, error) {
addr := internal_common.ParseAddr(address)
return s.b.GetBalance(addr)
}
@ -493,11 +460,11 @@ var (
// GetMedianRawStakeSnapshot returns the raw median stake, only meant to be called on beaconchain
// explorer node
func (s *PublicBlockChainAPI) GetMedianRawStakeSnapshot() (uint64, error) {
func (s *PublicBlockChainAPI) GetMedianRawStakeSnapshot() (*big.Int, error) {
if s.b.IsBeaconChainExplorerNode() {
return s.GetMedianRawStakeSnapshot()
return s.b.GetMedianRawStakeSnapshot(), nil
}
return 0, errNotExplorerNode
return nil, errNotExplorerNode
}
// GetAllValidatorAddresses returns all validator addresses.

@ -73,8 +73,8 @@ func (s *PublicTransactionPoolAPI) GetTransactionsHistory(ctx context.Context, a
}
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) int {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr uint64) int {
if block, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)); block != nil {
return len(block.Transactions())
}
return 0
@ -89,8 +89,8 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Co
}
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index uint64) *RPCTransaction {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr uint64, index uint64) *RPCTransaction {
if block, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)); block != nil {
return newRPCTransactionFromBlockIndex(block, index)
}
return nil
@ -138,8 +138,8 @@ func (s *PublicTransactionPoolAPI) GetStakingTransactionByHash(ctx context.Conte
}
// GetStakingTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (s *PublicTransactionPoolAPI) GetStakingTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index uint64) *RPCStakingTransaction {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
func (s *PublicTransactionPoolAPI) GetStakingTransactionByBlockNumberAndIndex(ctx context.Context, blockNr uint64, index uint64) *RPCStakingTransaction {
if block, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)); block != nil {
return newRPCStakingTransactionFromBlockIndex(block, index)
}
return nil
@ -154,10 +154,10 @@ func (s *PublicTransactionPoolAPI) GetStakingTransactionByBlockHashAndIndex(ctx
}
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr string, blockNr rpc.BlockNumber) (uint64, error) {
func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr string, blockNr uint64) (uint64, error) {
address := internal_common.ParseAddr(addr)
// Ask transaction pool for the nonce which includes pending transactions
if blockNr == rpc.PendingBlockNumber {
if rpc.BlockNumber(blockNr) == rpc.PendingBlockNumber {
nonce, err := s.b.GetPoolNonce(ctx, address)
if err != nil {
return 0, err
@ -165,7 +165,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
return nonce, nil
}
// Resolve block number and use its state to ask for the nonce
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.BlockNumber(blockNr))
if state == nil || err != nil {
return 0, err
}

@ -122,31 +122,31 @@ func GetAPIs(b Backend) []rpc.API {
Public: true, // FIXME: change to false once IPC implemented
},
{
Namespace: "hmy_v2",
Namespace: "hmyv2",
Version: "1.0",
Service: apiv2.NewPublicHarmonyAPI(b),
Public: true,
},
{
Namespace: "hmy_v2",
Namespace: "hmyv2",
Version: "1.0",
Service: apiv2.NewPublicBlockChainAPI(b),
Public: true,
},
{
Namespace: "hmy_v2",
Namespace: "hmyv2",
Version: "1.0",
Service: apiv2.NewPublicTransactionPoolAPI(b, nonceLockV2),
Public: true,
},
{
Namespace: "hmy_v2",
Namespace: "hmyv2",
Version: "1.0",
Service: apiv2.NewPublicAccountAPI(b.AccountManager()),
Public: true,
},
{
Namespace: "hmy_v2",
Namespace: "hmyv2",
Version: "1.0",
Service: apiv2.NewDebugAPI(b),
Public: true, // FIXME: change to false once IPC implemented

@ -1,64 +0,0 @@
package main
import (
"encoding/gob"
"flag"
"fmt"
"os"
"path"
"reflect"
"github.com/golang/mock/mockgen/model"
pkg_ "github.com/ethereum/go-ethereum/log"
)
var output = flag.String("output", "", "The output file name, or empty to use stdout.")
func main() {
flag.Parse()
its := []struct {
sym string
typ reflect.Type
}{
{"Logger", reflect.TypeOf((*pkg_.Logger)(nil)).Elem()},
}
pkg := &model.Package{
// NOTE: This behaves contrary to documented behaviour if the
// package name is not the final component of the import path.
// The reflect package doesn't expose the package name, though.
Name: path.Base("github.com/ethereum/go-ethereum/log"),
}
for _, it := range its {
intf, err := model.InterfaceFromInterfaceType(it.typ)
if err != nil {
fmt.Fprintf(os.Stderr, "Reflection: %v\n", err)
os.Exit(1)
}
intf.Name = it.sym
pkg.Interfaces = append(pkg.Interfaces, intf)
}
outfile := os.Stdout
if len(*output) != 0 {
var err error
outfile, err = os.Create(*output)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to open output file %q", *output)
}
defer func() {
if err := outfile.Close(); err != nil {
fmt.Fprintf(os.Stderr, "failed to close output file %q", *output)
os.Exit(1)
}
}()
}
if err := gob.NewEncoder(outfile).Encode(pkg); err != nil {
fmt.Fprintf(os.Stderr, "gob encode: %v\n", err)
os.Exit(1)
}
}

@ -1,64 +0,0 @@
package main
import (
"encoding/gob"
"flag"
"fmt"
"os"
"path"
"reflect"
"github.com/golang/mock/mockgen/model"
pkg_ "github.com/ethereum/go-ethereum/log"
)
var output = flag.String("output", "", "The output file name, or empty to use stdout.")
func main() {
flag.Parse()
its := []struct {
sym string
typ reflect.Type
}{
{"Handler", reflect.TypeOf((*pkg_.Handler)(nil)).Elem()},
}
pkg := &model.Package{
// NOTE: This behaves contrary to documented behaviour if the
// package name is not the final component of the import path.
// The reflect package doesn't expose the package name, though.
Name: path.Base("github.com/ethereum/go-ethereum/log"),
}
for _, it := range its {
intf, err := model.InterfaceFromInterfaceType(it.typ)
if err != nil {
fmt.Fprintf(os.Stderr, "Reflection: %v\n", err)
os.Exit(1)
}
intf.Name = it.sym
pkg.Interfaces = append(pkg.Interfaces, intf)
}
outfile := os.Stdout
if len(*output) != 0 {
var err error
outfile, err = os.Create(*output)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to open output file %q", *output)
}
defer func() {
if err := outfile.Close(); err != nil {
fmt.Fprintf(os.Stderr, "failed to close output file %q", *output)
os.Exit(1)
}
}()
}
if err := gob.NewEncoder(outfile).Encode(pkg); err != nil {
fmt.Fprintf(os.Stderr, "gob encode: %v\n", err)
os.Exit(1)
}
}

@ -34,11 +34,11 @@ var (
wsHandler *rpc.Server
httpEndpoint = ""
wsEndpoint = ""
httpModules = []string{"hmy", "hmy_v2", "net", "net_v2", "explorer"}
httpModules = []string{"hmy", "hmyv2", "net", "netv2", "explorer"}
httpVirtualHosts = []string{"*"}
httpTimeouts = rpc.DefaultHTTPTimeouts
httpOrigins = []string{"*"}
wsModules = []string{"hmy", "hmy_v2", "net", "net_v2", "web3"}
wsModules = []string{"hmy", "hmyv2", "net", "netv2", "web3"}
wsOrigins = []string{"*"}
harmony *hmy.Harmony
)
@ -211,7 +211,7 @@ func (node *Node) APIs() []rpc.API {
Public: true,
},
{
Namespace: "net_v2",
Namespace: "netv2",
Version: "1.0",
Service: apiv2.NewPublicNetAPI(node.host, harmony.APIBackend.NetVersion()),
Public: true,

@ -1,10 +1,11 @@
package hostv2
//go:generate mockgen -source hostv2.go -destination=mock/hostv2_mock.go
//go:generate mockgen -source=hostv2.go -package=hostv2 -destination=hostv2_mock_for_test.go
import (
"context"
"fmt"
"os"
"sync"
"github.com/pkg/errors"
@ -34,16 +35,45 @@ const (
//numOutgoing = 16
)
// pubsub captures the pubsub interface we expect from libp2p.
type pubsub interface {
Publish(topic string, data []byte) error
Subscribe(topic string, opts ...libp2p_pubsub.SubOpt) (*libp2p_pubsub.Subscription, error)
// topicHandle is a pubsub topic handle.
type topicHandle interface {
Publish(ctx context.Context, data []byte) error
Subscribe() (subscription, error)
}
type topicHandleImpl struct {
t *libp2p_pubsub.Topic
}
func (th topicHandleImpl) Publish(ctx context.Context, data []byte) error {
return th.t.Publish(ctx, data)
}
func (th topicHandleImpl) Subscribe() (subscription, error) {
return th.t.Subscribe()
}
type topicJoiner interface {
JoinTopic(topic string) (topicHandle, error)
}
type topicJoinerImpl struct {
pubsub *libp2p_pubsub.PubSub
}
func (tj topicJoinerImpl) JoinTopic(topic string) (topicHandle, error) {
th, err := tj.pubsub.Join(topic)
if err != nil {
return nil, err
}
return topicHandleImpl{th}, nil
}
// HostV2 is the version 2 p2p host
type HostV2 struct {
h libp2p_host.Host
pubsub pubsub
joiner topicJoiner
joined map[string]topicHandle
self p2p.Peer
priKey libp2p_crypto.PrivKey
lock sync.Mutex
@ -55,16 +85,36 @@ type HostV2 struct {
logger *zerolog.Logger
}
func (host *HostV2) getTopic(topic string) (topicHandle, error) {
host.lock.Lock()
defer host.lock.Unlock()
if t, ok := host.joined[topic]; ok {
return t, nil
} else if t, err := host.joiner.JoinTopic(topic); err != nil {
return nil, errors.Wrapf(err, "cannot join pubsub topic %x", topic)
} else {
host.joined[topic] = t
return t, nil
}
}
// SendMessageToGroups sends a message to one or more multicast groups.
func (host *HostV2) SendMessageToGroups(groups []nodeconfig.GroupID, msg []byte) error {
var error error
// It returns a nil error if and only if it has succeeded to schedule the given
// message for sending.
func (host *HostV2) SendMessageToGroups(groups []nodeconfig.GroupID, msg []byte) (err error) {
for _, group := range groups {
err := host.pubsub.Publish(string(group), msg)
if err != nil {
error = err
t, e := host.getTopic(string(group))
if e != nil {
err = e
continue
}
e = t.Publish(context.Background(), msg)
if e != nil {
err = e
continue
}
}
return error
return err
}
// subscription captures the subscription interface we expect from libp2p.
@ -105,10 +155,14 @@ func (r *GroupReceiverImpl) Receive(ctx context.Context) (
func (host *HostV2) GroupReceiver(group nodeconfig.GroupID) (
receiver p2p.GroupReceiver, err error,
) {
sub, err := host.pubsub.Subscribe(string(group))
t, err := host.getTopic(string(group))
if err != nil {
return nil, err
}
sub, err := t.Subscribe()
if err != nil {
return nil, errors.Wrapf(err, "cannot subscribe to topic %x", group)
}
return &GroupReceiverImpl{sub: sub}, nil
}
@ -173,8 +227,16 @@ func New(self *p2p.Peer, priKey libp2p_crypto.PrivKey) (*HostV2, error) {
if err != nil {
return nil, errors.Wrapf(err, "cannot initialize libp2p host")
}
pubsub, err := libp2p_pubsub.NewGossipSub(ctx, p2pHost)
// pubsub, err := libp2p_pubsub.NewFloodSub(ctx, p2pHost)
traceFile := os.Getenv("P2P_TRACEFILE")
var options = make([]libp2p_pubsub.Option, 0, 0)
// increase the peer outbound queue size from default 32 to 64
options = append(options, libp2p_pubsub.WithPeerOutboundQueueSize(64))
if len(traceFile) > 0 {
tracer, _ := libp2p_pubsub.NewJSONTracer(traceFile)
options = append(options, libp2p_pubsub.WithEventTracer(tracer))
}
pubsub, err := libp2p_pubsub.NewGossipSub(ctx, p2pHost, options...)
if err != nil {
return nil, errors.Wrapf(err, "cannot initialize libp2p pubsub")
}
@ -185,7 +247,8 @@ func New(self *p2p.Peer, priKey libp2p_crypto.PrivKey) (*HostV2, error) {
// has to save the private key for host
h := &HostV2{
h: p2pHost,
pubsub: pubsub,
joiner: topicJoinerImpl{pubsub},
joined: map[string]topicHandle{},
self: *self,
priKey: priKey,
logger: &subLogger,

@ -1,8 +1,8 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: hostv2.go
// Package mock_hostv2 is a generated GoMock package.
package mock_hostv2
// Package hostv2 is a generated GoMock package.
package hostv2
import (
context "context"
@ -11,61 +11,94 @@ import (
reflect "reflect"
)
// Mockpubsub is a mock of pubsub interface
type Mockpubsub struct {
// MocktopicHandle is a mock of topicHandle interface
type MocktopicHandle struct {
ctrl *gomock.Controller
recorder *MockpubsubMockRecorder
recorder *MocktopicHandleMockRecorder
}
// MockpubsubMockRecorder is the mock recorder for Mockpubsub
type MockpubsubMockRecorder struct {
mock *Mockpubsub
// MocktopicHandleMockRecorder is the mock recorder for MocktopicHandle
type MocktopicHandleMockRecorder struct {
mock *MocktopicHandle
}
// NewMockpubsub creates a new mock instance
func NewMockpubsub(ctrl *gomock.Controller) *Mockpubsub {
mock := &Mockpubsub{ctrl: ctrl}
mock.recorder = &MockpubsubMockRecorder{mock}
// NewMocktopicHandle creates a new mock instance
func NewMocktopicHandle(ctrl *gomock.Controller) *MocktopicHandle {
mock := &MocktopicHandle{ctrl: ctrl}
mock.recorder = &MocktopicHandleMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *Mockpubsub) EXPECT() *MockpubsubMockRecorder {
func (m *MocktopicHandle) EXPECT() *MocktopicHandleMockRecorder {
return m.recorder
}
// Publish mocks base method
func (m *Mockpubsub) Publish(topic string, data []byte) error {
func (m *MocktopicHandle) Publish(ctx context.Context, data []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Publish", topic, data)
ret := m.ctrl.Call(m, "Publish", ctx, data)
ret0, _ := ret[0].(error)
return ret0
}
// Publish indicates an expected call of Publish
func (mr *MockpubsubMockRecorder) Publish(topic, data interface{}) *gomock.Call {
func (mr *MocktopicHandleMockRecorder) Publish(ctx, data interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*Mockpubsub)(nil).Publish), topic, data)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MocktopicHandle)(nil).Publish), ctx, data)
}
// Subscribe mocks base method
func (m *Mockpubsub) Subscribe(topic string, opts ...go_libp2p_pubsub.SubOpt) (*go_libp2p_pubsub.Subscription, error) {
func (m *MocktopicHandle) Subscribe() (subscription, error) {
m.ctrl.T.Helper()
varargs := []interface{}{topic}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Subscribe", varargs...)
ret0, _ := ret[0].(*go_libp2p_pubsub.Subscription)
ret := m.ctrl.Call(m, "Subscribe")
ret0, _ := ret[0].(subscription)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Subscribe indicates an expected call of Subscribe
func (mr *MockpubsubMockRecorder) Subscribe(topic interface{}, opts ...interface{}) *gomock.Call {
func (mr *MocktopicHandleMockRecorder) Subscribe() *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{topic}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*Mockpubsub)(nil).Subscribe), varargs...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MocktopicHandle)(nil).Subscribe))
}
// MocktopicJoiner is a mock of topicJoiner interface
type MocktopicJoiner struct {
ctrl *gomock.Controller
recorder *MocktopicJoinerMockRecorder
}
// MocktopicJoinerMockRecorder is the mock recorder for MocktopicJoiner
type MocktopicJoinerMockRecorder struct {
mock *MocktopicJoiner
}
// NewMocktopicJoiner creates a new mock instance
func NewMocktopicJoiner(ctrl *gomock.Controller) *MocktopicJoiner {
mock := &MocktopicJoiner{ctrl: ctrl}
mock.recorder = &MocktopicJoinerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MocktopicJoiner) EXPECT() *MocktopicJoinerMockRecorder {
return m.recorder
}
// JoinTopic mocks base method
func (m *MocktopicJoiner) JoinTopic(topic string) (topicHandle, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "JoinTopic", topic)
ret0, _ := ret[0].(topicHandle)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// JoinTopic indicates an expected call of JoinTopic
func (mr *MocktopicJoinerMockRecorder) JoinTopic(topic interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "JoinTopic", reflect.TypeOf((*MocktopicJoiner)(nil).JoinTopic), topic)
}
// Mocksubscription is a mock of subscription interface

@ -7,43 +7,87 @@ import (
"testing"
"github.com/golang/mock/gomock"
libp2p_peer "github.com/libp2p/go-libp2p-peer"
libp2p_peer "github.com/libp2p/go-libp2p-core/peer"
libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub"
libp2p_pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
mock "github.com/harmony-one/harmony/p2p/host/hostv2/mock"
)
func TestHostV2_SendMessageToGroups(t *testing.T) {
t.Run("Basic", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
groups := []nodeconfig.GroupID{"ABC", "DEF"}
okTopic := NewMocktopicHandle(mc)
newTopic := NewMocktopicHandle(mc)
groups := []nodeconfig.GroupID{"OK", "New"}
data := []byte{1, 2, 3}
pubsub := mock.NewMockpubsub(mc)
joined := map[string]topicHandle{"OK": okTopic}
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: joined}
gomock.InOrder(
pubsub.EXPECT().Publish("ABC", data),
pubsub.EXPECT().Publish("DEF", data),
// okTopic is already in joined map, JoinTopic shouldn't be called
joiner.EXPECT().JoinTopic("OK").Times(0),
okTopic.EXPECT().Publish(context.TODO(), data).Return(nil),
// newTopic is not in joined map, JoinTopic should be called
joiner.EXPECT().JoinTopic("New").Return(newTopic, nil),
newTopic.EXPECT().Publish(context.TODO(), data).Return(nil),
)
host := &HostV2{pubsub: pubsub}
if err := host.SendMessageToGroups(groups, data); err != nil {
err := host.SendMessageToGroups(groups, data)
if err != nil {
t.Errorf("expected no error; got %v", err)
}
})
t.Run("Error", func(t *testing.T) {
t.Run("JoinError", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
okTopic := NewMocktopicHandle(mc)
groups := []nodeconfig.GroupID{"Error", "OK"}
data := []byte{1, 2, 3}
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
gomock.InOrder(
// Make first join return an error
joiner.EXPECT().JoinTopic("Error").Return(nil, errors.New("join error")),
// Subsequent topics should still be processed after an error
joiner.EXPECT().JoinTopic("OK").Return(okTopic, nil),
okTopic.EXPECT().Publish(context.TODO(), data).Return(nil),
)
err := host.SendMessageToGroups(groups, data)
if err == nil {
t.Error("expected an error; got nil")
}
})
t.Run("PublishError", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
groups := []nodeconfig.GroupID{"ABC", "DEF"}
okTopic := NewMocktopicHandle(mc)
erringTopic := NewMocktopicHandle(mc)
groups := []nodeconfig.GroupID{"Error", "OK"}
data := []byte{1, 2, 3}
pubsub := mock.NewMockpubsub(mc)
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
gomock.InOrder(
pubsub.EXPECT().Publish("ABC", data).Return(errors.New("FIAL")),
pubsub.EXPECT().Publish("DEF", data), // Should not early-return
// Make first publish return an error
joiner.EXPECT().JoinTopic("Error").Return(erringTopic, nil),
erringTopic.EXPECT().Publish(context.TODO(), data).Return(errors.New("publish error")),
// Subsequent topics should still be processed after an error
joiner.EXPECT().JoinTopic("OK").Return(okTopic, nil),
okTopic.EXPECT().Publish(context.TODO(), data).Return(nil),
)
host := &HostV2{pubsub: pubsub}
if err := host.SendMessageToGroups(groups, data); err == nil {
t.Error("expected an error but got none")
t.Error("expected an error; got nil")
}
})
}
@ -51,10 +95,14 @@ func TestHostV2_SendMessageToGroups(t *testing.T) {
func TestGroupReceiver_Close(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
sub := mock.NewMocksubscription(mc)
sub := NewMocksubscription(mc)
sub.EXPECT().Cancel()
receiver := GroupReceiverImpl{sub: sub}
if err := receiver.Close(); err != nil {
err := receiver.Close()
if err != nil {
t.Errorf("expected no error but got %v", err)
}
}
@ -65,46 +113,71 @@ func pubsubMessage(from libp2p_peer.ID, data []byte) *libp2p_pubsub.Message {
}
func TestGroupReceiver_Receive(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
sub := mock.NewMocksubscription(mc)
ctx := context.Background()
gomock.InOrder(
sub.EXPECT().Next(ctx).Return(pubsubMessage("ABC", []byte{1, 2, 3}), nil),
sub.EXPECT().Next(ctx).Return(pubsubMessage("DEF", []byte{4, 5, 6}), nil),
sub.EXPECT().Next(ctx).Return(nil, errors.New("FIAL")),
)
receiver := GroupReceiverImpl{sub: sub}
verify := func(sender libp2p_peer.ID, msg []byte, shouldError bool) {
t.Run("OK", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
ctx := context.Background()
sub := NewMocksubscription(mc)
receiver := GroupReceiverImpl{sub: sub}
wantSender := libp2p_peer.ID("OK")
wantMsg := []byte{1, 2, 3}
sub.EXPECT().Next(ctx).Return(pubsubMessage(wantSender, wantMsg), nil)
gotMsg, gotSender, err := receiver.Receive(ctx)
if (err != nil) != shouldError {
if shouldError {
t.Error("expected an error but got none")
} else {
t.Errorf("expected no error but got %v", err)
}
if err != nil {
t.Errorf("expected no error; got %v", err)
}
if gotSender != sender {
t.Errorf("expected sender %v but got %v", sender, gotSender)
if gotSender != wantSender {
t.Errorf("expected sender %v; got %v", wantSender, gotSender)
}
if !reflect.DeepEqual(gotMsg, msg) {
t.Errorf("expected message %v but got %v", msg, gotMsg)
if !reflect.DeepEqual(gotMsg, wantMsg) {
t.Errorf("expected message %v; got %v", wantMsg, gotMsg)
}
}
verify("ABC", []byte{1, 2, 3}, false)
verify("DEF", []byte{4, 5, 6}, false)
verify("", nil, true)
})
t.Run("Error", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
ctx := context.Background()
sub := NewMocksubscription(mc)
receiver := GroupReceiverImpl{sub: sub}
sub.EXPECT().Next(ctx).Return(nil, errors.New("receive error"))
msg, sender, err := receiver.Receive(ctx)
if err == nil {
t.Error("expected an error; got nil")
}
if sender != "" {
t.Errorf("expected empty sender; got %v", sender)
}
if len(msg) > 0 {
t.Errorf("expected empty message; got %v", msg)
}
})
}
func TestHostV2_GroupReceiver(t *testing.T) {
t.Run("Basic", func(t *testing.T) {
t.Run("New", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
sub := &libp2p_pubsub.Subscription{}
pubsub := mock.NewMockpubsub(mc)
pubsub.EXPECT().Subscribe("ABC").Return(sub, nil)
host := &HostV2{pubsub: pubsub}
topic := NewMocktopicHandle(mc)
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
gomock.InOrder(
joiner.EXPECT().JoinTopic("ABC").Return(topic, nil),
topic.EXPECT().Subscribe().Return(sub, nil),
)
gotReceiver, err := host.GroupReceiver("ABC")
if r, ok := gotReceiver.(*GroupReceiverImpl); !ok {
t.Errorf("expected a hostv2 GroupReceiverImpl; got %v", gotReceiver)
} else if r.sub != sub {
@ -114,13 +187,39 @@ func TestHostV2_GroupReceiver(t *testing.T) {
t.Errorf("expected no error; got %v", err)
}
})
t.Run("Error", func(t *testing.T) {
t.Run("JoinError", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
joiner.EXPECT().JoinTopic("ABC").Return(nil, errors.New("join error"))
gotReceiver, err := host.GroupReceiver("ABC")
if gotReceiver != nil {
t.Errorf("expected a nil hostv2 GroupReceiverImpl; got %v", gotReceiver)
}
if err == nil {
t.Error("expected an error; got none")
}
})
t.Run("SubscribeError", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
pubsub := mock.NewMockpubsub(mc)
pubsub.EXPECT().Subscribe("ABC").Return(nil, errors.New("FIAL"))
host := &HostV2{pubsub: pubsub}
topic := NewMocktopicHandle(mc)
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
gomock.InOrder(
joiner.EXPECT().JoinTopic("ABC").Return(topic, nil),
topic.EXPECT().Subscribe().Return(nil, errors.New("subscription error")),
)
gotReceiver, err := host.GroupReceiver("ABC")
if gotReceiver != nil {
t.Errorf("expected a nil hostv2 GroupReceiverImpl; got %v", gotReceiver)
}
@ -136,3 +235,65 @@ func TestHostV2_GroupReceiver(t *testing.T) {
}
})
}
func TestHostV2_getTopic(t *testing.T) {
t.Run("NewOK", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
joiner := NewMocktopicJoiner(mc)
want := NewMocktopicHandle(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
joiner.EXPECT().JoinTopic("ABC").Return(want, nil)
got, err := host.getTopic("ABC")
if err != nil {
t.Errorf("want nil error; got %v", err)
}
if got != want {
t.Errorf("want topic handle %v; got %v", want, got)
}
if _, ok := host.joined["ABC"]; !ok {
t.Error("topic not found in joined map")
}
})
t.Run("NewError", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
joiner := NewMocktopicJoiner(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{}}
joiner.EXPECT().JoinTopic("ABC").Return(nil, errors.New("OMG"))
got, err := host.getTopic("ABC")
if err == nil {
t.Error("want non-nil error; got nil")
}
if got != nil {
t.Errorf("want nil handle; got %v", got)
}
})
t.Run("Existing", func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
joiner := NewMocktopicJoiner(mc)
want := NewMocktopicHandle(mc)
host := &HostV2{joiner: joiner, joined: map[string]topicHandle{"ABC": want}}
joiner.EXPECT().JoinTopic("ABC").Times(0)
got, err := host.getTopic("ABC")
if err != nil {
t.Errorf("want nil error; got %v", err)
}
if got != want {
t.Errorf("want topic handle %v; got %v", want, got)
}
})
}

@ -126,7 +126,13 @@ function build_only
fi
done
pushd $BINDIR
$MD5 "${!SRC[@]}" > md5sum.txt
for lib in "${!LIB[@]}"; do
if [ -e ${LIB[$lib]} ]; then
cp -pf ${LIB[$lib]} .
fi
done
$MD5 "${!SRC[@]}" "${!LIB[@]}" > md5sum.txt
popd
}

@ -6,4 +6,5 @@ exec git ls-files '*.go' | grep -v \
-e '/host_mock\.go' \
-e '/mock/[^/]*\.go' \
-e '/mock_[^/]*/[^/]*\.go' \
-e '_mock_for_test\.go' \
-e '/gen_[^/]*\.go'

@ -122,6 +122,7 @@ options:
-z run in staking mode
-y run in legacy, foundational-node mode (default)
-M support multi-key mode (default: off)
-A enable archival node mode (default: off)
-B blacklist specify file containing blacklisted accounts as a newline delimited file (default: ./blacklist.txt)
examples:
@ -173,12 +174,14 @@ download_harmony_db=false
public_rpc=false
staking_mode=false
multi_key=false
archival=false
blacklist=./blacklist.txt
archival=false
${BLSKEYFILE=}
unset OPTIND OPTARG opt
OPTIND=1
while getopts :1chk:sSp:dDmN:tT:i:ba:U:PvVyzn:MB: opt
while getopts :1chk:sSp:dDmN:tT:i:ba:U:PvVyzn:MAB: opt
do
case "${opt}" in
'?') usage "unrecognized option -${OPTARG}";;
@ -210,6 +213,7 @@ do
exit 0 ;;
z) staking_mode=true;;
y) staking_mode=false;;
A) archival=true;;
*) err 70 "unhandled option -${OPTARG}";; # EX_SOFTWARE
esac
done
@ -662,6 +666,9 @@ do
-dns_zone="${dns_zone}"
-blacklist="${blacklist}"
)
args+=(
-is_archival="${archival}"
)
if ! ${multi_key}; then
args+=(
-blskey_file "${BLSKEYFILE}"

Loading…
Cancel
Save