test(tester):update network.toml in cluster nodes

This commit is contained in:
jzhe 2020-12-04 19:58:01 +08:00 committed by Lizen0512
parent 4c9c5cbe56
commit 00c38a417d
27 changed files with 393 additions and 236 deletions

View File

@ -87,7 +87,7 @@ func start(ctx *cli.Context) error {
}
// start grpc service
b, err := grpc.NewChainBrokerService(api, repo.Config, repo.Genesis)
b, err := grpc.NewChainBrokerService(api, repo.Config, &repo.Config.Genesis)
if err != nil {
return err
}

View File

@ -51,3 +51,11 @@ server_key_path = "certs/server.key"
[executor]
type = "serial" # opensource version only supports serial type, commercial version supports serial and parallel types
[genesis]
addresses = [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]

View File

@ -1,8 +0,0 @@
{
"addresses": [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]
}

View File

@ -1,18 +1,26 @@
id = 1 # self id
N = 4 # the number of cluster nodes
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4001/p2p/QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
id = 1
n = 4
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4002/p2p/QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
id = 1
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
[[nodes]]
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
id = 2
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4003/p2p/QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
id = 3
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4004/p2p/QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
id = 4
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"

3
go.mod
View File

@ -27,11 +27,12 @@ require (
github.com/magiconair/properties v1.8.4
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20201125025329-ac1187099a88
github.com/meshplus/bitxhub-kit v1.1.2-0.20201203072410-8a0383a6870d
github.com/meshplus/bitxhub-model v1.1.2-0.20201208133437-73fa50d5efed
github.com/meshplus/bitxhub-model v1.1.2-0.20201209072914-6846fa78ff35
github.com/meshplus/go-lightp2p v0.0.0-20201203044909-e09b34cd93ab
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.2.2
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6
github.com/pelletier/go-toml v1.2.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.5.0
github.com/rogpeppe/go-internal v1.5.2 // indirect

8
go.sum
View File

@ -602,6 +602,8 @@ github.com/meshplus/bitxhub-kit v1.0.0/go.mod h1:7cWyhXWZfrQ3+EaxkRoXfuiG3Y5R9DX
github.com/meshplus/bitxhub-kit v1.1.2-0.20201021105954-468d0a9d7957 h1:1a3wYo2HQw9/yg5LfAPJ1En90pPbMwRlaVssxOLG97w=
github.com/meshplus/bitxhub-kit v1.1.2-0.20201021105954-468d0a9d7957/go.mod h1:r4l4iqn0RPJreb/OmoYKfjCjQJrXpZX++6Qc31VG/1k=
github.com/meshplus/bitxhub-kit v1.1.2-0.20201023030558-9f36554d5d5d/go.mod h1:r4l4iqn0RPJreb/OmoYKfjCjQJrXpZX++6Qc31VG/1k=
github.com/meshplus/bitxhub-kit v1.1.2-0.20201127072239-fddea8940bae h1:G9ENjV078RtGauPVUvpPn2c83h9uXQvvzdQpOwdSVUM=
github.com/meshplus/bitxhub-kit v1.1.2-0.20201127072239-fddea8940bae/go.mod h1:KR7ZlXhII9n0Bu8viaZTScvXCYn0MCQnYlsTvHPp0XA=
github.com/meshplus/bitxhub-kit v1.1.2-0.20201203072410-8a0383a6870d h1:J9tzTNf29mR0r97An3KoAtZQYlwpNhlMItWKyzKJLHU=
github.com/meshplus/bitxhub-kit v1.1.2-0.20201203072410-8a0383a6870d/go.mod h1:KR7ZlXhII9n0Bu8viaZTScvXCYn0MCQnYlsTvHPp0XA=
github.com/meshplus/bitxhub-model v1.0.0-rc3/go.mod h1:ZCctQIYTlE3vJ8Lhkrgs9bWwNA+Dw4JzojOSIzLVU6E=
@ -610,10 +612,8 @@ github.com/meshplus/bitxhub-model v1.1.2-0.20201021152621-0b3c17c54b23 h1:ys+2Vj
github.com/meshplus/bitxhub-model v1.1.2-0.20201021152621-0b3c17c54b23/go.mod h1:4qWBZx5wv7WZzUqiuBsbkQqQ2Ju8aOFpsoNpBBNy8Us=
github.com/meshplus/bitxhub-model v1.1.2-0.20201118055706-510eb971b4c6 h1:M2j5n9XRgNc9baS6JEfpRW+ygKiKqorUVfvjpdlOld0=
github.com/meshplus/bitxhub-model v1.1.2-0.20201118055706-510eb971b4c6/go.mod h1:4qWBZx5wv7WZzUqiuBsbkQqQ2Ju8aOFpsoNpBBNy8Us=
github.com/meshplus/bitxhub-model v1.1.2-0.20201208115750-c5dd9f9cac29 h1:bwxI8eW5+w3h45sv/Llif5gZMRF+Tb/MxvAPtAJ+arw=
github.com/meshplus/bitxhub-model v1.1.2-0.20201208115750-c5dd9f9cac29/go.mod h1:sk7glP/0M9G9On4SN6rMPaLGqet8Uu35wA65Mxc3Cms=
github.com/meshplus/bitxhub-model v1.1.2-0.20201208133437-73fa50d5efed h1:0EG9U1b17KKpg9i7QIiEMihfgBNe8CrF2il7200hZSI=
github.com/meshplus/bitxhub-model v1.1.2-0.20201208133437-73fa50d5efed/go.mod h1:sk7glP/0M9G9On4SN6rMPaLGqet8Uu35wA65Mxc3Cms=
github.com/meshplus/bitxhub-model v1.1.2-0.20201209072914-6846fa78ff35 h1:fuY1VlVKUa58108lODiQpsVypGiuYjPlEawx6xd6uyA=
github.com/meshplus/bitxhub-model v1.1.2-0.20201209072914-6846fa78ff35/go.mod h1:sk7glP/0M9G9On4SN6rMPaLGqet8Uu35wA65Mxc3Cms=
github.com/meshplus/go-lightp2p v0.0.0-20201203044909-e09b34cd93ab h1:JclTakVV0dcXxl/dScmN77htnYe3n19hh7m2eMk9Abs=
github.com/meshplus/go-lightp2p v0.0.0-20201203044909-e09b34cd93ab/go.mod h1:L3pEzDMouz+xcIVwG2fj+mAsM95GAkzoo7cEd2CzmCQ=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=

View File

@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/meshplus/bitxhub-kit/storage/blockfile"
"github.com/meshplus/bitxhub-kit/storage/leveldb"
"github.com/meshplus/bitxhub-kit/types"
_ "github.com/meshplus/bitxhub/imports"
"github.com/meshplus/bitxhub/internal/executor"
"github.com/meshplus/bitxhub/internal/ledger"
@ -51,13 +50,7 @@ func NewBitXHub(rep *repo.Repo) (*BitXHub, error) {
chainMeta := bxh.Ledger.GetChainMeta()
m := make(map[uint64]types.Address)
if !rep.Config.Solo {
for i, node := range rep.NetworkConfig.Nodes {
m[node.ID] = *types.NewAddressByStr(rep.Genesis.Addresses[i])
}
}
m := rep.NetworkConfig.GetVpAccount()
order, err := orderplg.New(
order.WithRepoRoot(repoRoot),
@ -122,7 +115,7 @@ func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
}
if rwLdg.GetChainMeta().Height == 0 {
if err := genesis.Initialize(rep.Genesis, rwLdg); err != nil {
if err := genesis.Initialize(&rep.Config.Genesis, rwLdg); err != nil {
return nil, err
}
logger.Info("Initialize genesis")
@ -173,13 +166,7 @@ func NewTesterBitXHub(rep *repo.Repo) (*BitXHub, error) {
chainMeta := bxh.Ledger.GetChainMeta()
m := make(map[uint64]types.Address)
if !rep.Config.Solo {
for i, node := range rep.NetworkConfig.Nodes {
m[node.ID] = *types.NewAddressByStr(rep.Genesis.Addresses[i])
}
}
m := rep.NetworkConfig.GetVpAccount()
order, err := etcdraft.NewNode(
order.WithRepoRoot(repoRoot),
@ -281,7 +268,7 @@ func (bxh *BitXHub) Stop() error {
func (bxh *BitXHub) printLogo() {
for {
time.Sleep(100 * time.Millisecond)
err :=bxh.Order.Ready()
err := bxh.Order.Ready()
if err == nil {
bxh.logger.WithFields(logrus.Fields{
"plugin_path": bxh.repo.Config.Order.Plugin,

View File

@ -2,7 +2,6 @@ package repo
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
@ -41,6 +40,7 @@ type Config struct {
Txpool `json:"txpool"`
Order `json:"order"`
Executor `json:"executor"`
Genesis `json:"genesis"`
Security Security `toml:"security" json:"security"`
}
@ -222,16 +222,3 @@ func PathRootWithDefault(path string) (string, error) {
return path, nil
}
func loadGenesis(repoRoot string) (*Genesis, error) {
genesis := &Genesis{}
if err := ReadConfig(filepath.Join(repoRoot, "genesis.json"), "json", genesis); err != nil {
return nil, err
}
if len(genesis.Addresses) == 0 {
return nil, fmt.Errorf("wrong genesis address number")
}
return genesis, nil
}

View File

@ -1,44 +1,40 @@
package repo
import (
"bytes"
"fmt"
"github.com/libp2p/go-libp2p-core/crypto"
crypto2 "github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub/pkg/cert"
"io/ioutil"
"path/filepath"
"strings"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
crypto2 "github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/pkg/cert"
ma "github.com/multiformats/go-multiaddr"
"github.com/pelletier/go-toml"
"github.com/spf13/viper"
)
type NetworkConfig struct {
ID uint64
N uint64
LocalAddr string
Nodes []*NetworkNodes
OtherNodes map[uint64]*peer.AddrInfo
ID uint64 `toml:"id" json:"id"`
N uint64 `toml:"n" json:"n"`
LocalAddr string `toml:"local_addr, omitempty" json:"local_addr"`
Nodes []*NetworkNodes `toml:"nodes" json:"nodes"`
Genesis Genesis `toml:"genesis, omitempty" json:"genesis"`
}
type NetworkNodes struct {
ID uint64
Addr string
ID uint64 `toml:"id" json:"id"`
Pid string `toml:"pid" json:"pid"`
Hosts []string `toml:"hosts" json:"hosts"`
Account string `toml:"account" json:"account"`
}
// AddrToPeerInfo transfer addr to PeerInfo
// addr example: "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
func AddrToPeerInfo(multiAddr string) (*peer.AddrInfo, error) {
maddr, err := ma.NewMultiaddr(multiAddr)
if err != nil {
return nil, err
}
return peer.AddrInfoFromP2pAddr(maddr)
}
func loadNetworkConfig(repoRoot string) (*NetworkConfig, error) {
networkConfig := &NetworkConfig{}
func loadNetworkConfig(repoRoot string, genesis Genesis) (*NetworkConfig, error) {
networkConfig := &NetworkConfig{Genesis: genesis}
if err := ReadConfig(filepath.Join(repoRoot, "network.toml"), "toml", networkConfig); err != nil {
return nil, err
}
@ -49,8 +45,11 @@ func loadNetworkConfig(repoRoot string) (*NetworkConfig, error) {
for _, node := range networkConfig.Nodes {
if node.ID == networkConfig.ID {
networkConfig.LocalAddr = node.Addr
addr, err := ma.NewMultiaddr(networkConfig.LocalAddr)
if len(node.Hosts) == 0 {
return nil, fmt.Errorf("no hosts found by node:%d", node.ID)
}
networkConfig.LocalAddr = node.Hosts[0]
addr, err := ma.NewMultiaddr(fmt.Sprintf("%s%s", node.Hosts[0], node.Pid))
if err != nil {
return nil, fmt.Errorf("new multiaddr: %w", err)
}
@ -68,24 +67,103 @@ func loadNetworkConfig(repoRoot string) (*NetworkConfig, error) {
}
networkConfig.LocalAddr = networkConfig.LocalAddr[:idx]
nodes := networkConfig.Nodes
m := make(map[uint64]*peer.AddrInfo)
for _, node := range nodes {
if node.ID != networkConfig.ID {
addr, err := AddrToPeerInfo(node.Addr)
if err != nil {
return nil, fmt.Errorf("wrong network addr: %w", err)
}
m[node.ID] = addr
}
}
networkConfig.OtherNodes = m
return networkConfig, nil
}
// GetVpInfos gets vp info from network config
func (config *NetworkConfig) GetVpInfos() []*pb.VpInfo {
vpGenesisInfos := make([]*pb.VpInfo, 0, len(config.Nodes))
for _, node := range config.Nodes {
vpGenesisInfos = append(vpGenesisInfos, &pb.VpInfo{
Id: node.ID,
Pid: node.Pid,
Account: node.Account,
Hosts: node.Hosts,
})
}
return vpGenesisInfos
}
// GetVpGenesisAccount gets genesis address from network config
func (config *NetworkConfig) GetVpGenesisAccount() map[uint64]types.Address {
m := make(map[uint64]types.Address)
for i, address := range config.Genesis.Addresses {
m[uint64(i)+1] = *types.NewAddressByStr(address)
}
return m
}
// GetVpAccount gets genesis address from network config
func (config *NetworkConfig) GetVpAccount() map[uint64]types.Address {
m := make(map[uint64]types.Address)
for _, node := range config.Nodes {
m[node.ID] = *types.NewAddressByStr(node.Account)
}
return m
}
// GetPeers gets all peers from network config
func (config *NetworkConfig) GetPeers() (map[uint64]*peer.AddrInfo, error) {
peers := make(map[uint64]*peer.AddrInfo)
for _, node := range config.Nodes {
if len(node.Hosts) == 0 {
return nil, fmt.Errorf("no hosts found by node:%d", node.ID)
}
multiaddr, err := ma.NewMultiaddr(fmt.Sprintf("%s%s", node.Hosts[0], node.Pid))
if err != nil {
return nil, fmt.Errorf("new Multiaddr error:%w", err)
}
addrInfo, err := peer.AddrInfoFromP2pAddr(multiaddr)
if err != nil {
return nil, err
}
for i := 1; i < len(node.Hosts); i++ {
multiaddr, err := ma.NewMultiaddr(fmt.Sprintf("%s%s", node.Hosts[i], node.Pid))
if err != nil {
return nil, fmt.Errorf("new Multiaddr error:%w", err)
}
addrInfo.Addrs = append(addrInfo.Addrs, multiaddr)
}
peers[node.ID] = addrInfo
}
return peers, nil
}
func RewriteNetworkConfig(repoRoot string, infos []*pb.VpInfo) error {
networkConfig := &NetworkConfig{}
v := viper.New()
v.SetConfigFile(filepath.Join(repoRoot, "network.toml"))
v.SetConfigType("toml")
if err := v.ReadInConfig(); err != nil {
return err
}
if err := v.Unmarshal(networkConfig); err != nil {
return err
}
nodes := make([]*NetworkNodes, 0, len(infos))
for _, info := range infos {
node := &NetworkNodes{
ID: info.Id,
Pid: info.Pid,
Account: info.Account,
Hosts: info.Hosts,
}
nodes = append(nodes, node)
}
networkConfig.Nodes = nodes
networkConfig.N = uint64(len(nodes))
data, err := toml.Marshal(*networkConfig)
if err != nil {
return err
}
err = v.ReadConfig(bytes.NewBuffer(data))
if err != nil {
return err
}
return v.WriteConfig()
}
// GetPidFromPrivFile gets pid from libp2p node priv file
func GetPidFromPrivFile(privPath string) (string, error) {

View File

@ -0,0 +1,69 @@
package repo
import (
"github.com/meshplus/bitxhub-model/pb"
"github.com/stretchr/testify/require"
"testing"
)
func TestNetworkConfig(t *testing.T) {
path := "./testdata"
cfg, err := loadNetworkConfig(path, Genesis{Addresses: []string{"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"}})
require.Nil(t, err)
peers, err := cfg.GetPeers()
require.Nil(t, err)
require.Equal(t, 4, len(peers))
accounts := cfg.GetVpGenesisAccount()
require.Equal(t, 4, len(accounts))
vpAccounts := cfg.GetVpAccount()
require.Equal(t, 4, len(vpAccounts))
vpInfos := cfg.GetVpInfos()
require.Equal(t, 4, len(vpInfos))
}
func TestRewriteNetworkConfig(t *testing.T) {
infos := make([]*pb.VpInfo, 0)
{
infos = append(infos, &pb.VpInfo{
Id: 1,
Hosts: []string{"/ip4/127.0.0.1/tcp/4001/p2p/"},
Pid: "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS",
Account: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
})
infos = append(infos, &pb.VpInfo{
Id: 2,
Hosts: []string{"/ip4/127.0.0.1/tcp/4002/p2p/"},
Pid: "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy",
Account: "0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
})
infos = append(infos, &pb.VpInfo{
Id: 3,
Hosts: []string{"/ip4/127.0.0.1/tcp/4003/p2p/"},
Pid: "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL",
Account: "0x97c8B516D19edBf575D72a172Af7F418BE498C37",
})
infos = append(infos, &pb.VpInfo{
Id: 4,
Hosts: []string{"/ip4/127.0.0.1/tcp/4004/p2p/"},
Pid: "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4",
Account: "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8",
})
infos = append(infos, &pb.VpInfo{
Id: 5,
Hosts: []string{"/ip4/127.0.0.1/tcp/4005/p2p/"},
Pid: "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E",
Account: "0xc0Ff2e0b3189132D815b8eb325bE1728",
})
}
err := RewriteNetworkConfig("./testdata", infos)
require.Nil(t, err)
err = RewriteNetworkConfig("./testdata", infos[:len(infos)-1])
require.Nil(t, err)
}

View File

@ -9,7 +9,6 @@ import (
type Repo struct {
Config *Config
NetworkConfig *NetworkConfig
Genesis *Genesis
Key *Key
Certs *Certs
}
@ -20,16 +19,11 @@ func Load(repoRoot string) (*Repo, error) {
return nil, err
}
networkConfig, err := loadNetworkConfig(repoRoot)
networkConfig, err := loadNetworkConfig(repoRoot, config.Genesis)
if err != nil {
return nil, fmt.Errorf("load network config: %w", err)
}
genesis, err := loadGenesis(repoRoot)
if err != nil {
return nil, fmt.Errorf("load genesis: %w", err)
}
certs, err := loadCerts(repoRoot)
if err != nil {
return nil, err
@ -43,7 +37,6 @@ func Load(repoRoot string) (*Repo, error) {
return &Repo{
Config: config,
NetworkConfig: networkConfig,
Genesis: genesis,
Key: key,
Certs: certs,
}, nil

View File

@ -1,18 +1,26 @@
id = 1 # self id
N = 4 # the number of cluster nodes
[[nodes]]
id = 1
addr = "/ip4/127.0.0.1/tcp/4001/p2p/QmYkQxwC3cj8HqxAnsgM1cSK5yPjkL8UySc21b1AhVF2Wf"
n = 4
[[nodes]]
id = 2
addr = "/ip4/127.0.0.1/tcp/4002/p2p/QmfHtWy4uqu3JvUUDpAq7oHXkpq5qkuY1Ffb6zngqXtpMi"
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
id = 1
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
[[nodes]]
id = 3
addr = "/ip4/127.0.0.1/tcp/4003/p2p/QmcpUhepA4tgkVvzW6WnxHCCk163CTLSiKatQeVSF8ro9z"
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
id = 2
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
[[nodes]]
id = 4
addr = "/ip4/127.0.0.1/tcp/4004/p2p/QmT3ghgJFboqYYM9B6p6ehJFGHoEqpaRCJBByWCCYgHHZt"
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
id = 3
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
[[nodes]]
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
id = 4
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"

View File

@ -26,7 +26,6 @@ import (
"github.com/meshplus/bitxhub/pkg/order"
"github.com/meshplus/bitxhub/pkg/peermgr"
"github.com/meshplus/bitxhub/pkg/peermgr/mock_peermgr"
ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -171,12 +170,26 @@ func generateTx() *pb.Transaction {
return tx
}
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string) {
func peers(id uint64, addrs []string, ids []string) []*repo.NetworkNodes {
m := make([]*repo.NetworkNodes, 0, len(addrs))
for i, addr := range addrs {
m = append(m, &repo.NetworkNodes{
ID: uint64(i + 1),
Account: "",
Pid: ids[i],
Hosts: []string{addr},
})
}
return m
}
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string, []string) {
var nodeKeys []crypto2.PrivKey
var privKeys []crypto.PrivateKey
var peers []string
var ids []string
port := 7001
port := 5001
for i := 0; i < peerCnt; i++ {
key, err := asym.GenerateKeyPair(crypto.ECDSA_P256)
@ -188,8 +201,9 @@ func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.Pr
id, err := peer.IDFromPublicKey(libp2pKey.GetPublic())
require.Nil(t, err)
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/%s", port, id)
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/", port)
peers = append(peers, peer)
ids = append(ids, id.String())
port++
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
@ -198,7 +212,7 @@ func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.Pr
privKeys = append(privKeys, privKey)
}
return nodeKeys, privKeys, peers
return nodeKeys, privKeys, peers, ids
}
func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, error) {
@ -215,23 +229,10 @@ func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, erro
return libp2pPrivKey, nil
}
func otherPeers(id uint64, addrs []string) map[uint64]*peer.AddrInfo {
m := make(map[uint64]*peer.AddrInfo)
for i, addr := range addrs {
if uint64(i+1) == id {
continue
}
addr, _ := ma.NewMultiaddr(addr)
pAddr, _ := peer.AddrInfoFromP2pAddr(addr)
m[uint64(i+1)] = pAddr
}
return m
}
func newSwarms(t *testing.T, peerCnt int) ([]*peermgr.Swarm, map[uint64]types.Address) {
var swarms []*peermgr.Swarm
nodes := make(map[uint64]types.Address)
nodeKeys, privKeys, addrs := genKeysAndConfig(t, peerCnt)
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
mockCtl := gomock.NewController(t)
mockLedger := mock_ledger.NewMockLedger(mockCtl)
@ -266,18 +267,12 @@ func newSwarms(t *testing.T, peerCnt int) ([]*peermgr.Swarm, map[uint64]types.Ad
},
},
}
var local string
id, err := peer.IDFromPublicKey(nodeKeys[i].GetPublic())
require.Nil(t, err)
if strings.HasSuffix(addrs[i], id.String()) {
idx := strings.LastIndex(addrs[i], "/p2p/")
local = addrs[i][:idx]
}
idx := strings.LastIndex(addrs[i], "/p2p/")
local := addrs[i][:idx]
repo.NetworkConfig.LocalAddr = local
repo.Key.Libp2pPrivKey = nodeKeys[i]
repo.Key.PrivKey = privKeys[i]
repo.NetworkConfig.OtherNodes = otherPeers(uint64(ID), addrs)
repo.NetworkConfig.Nodes = peers(uint64(i), addrs, ids)
address, err := privKeys[i].PublicKey().Address()
require.Nil(t, err)

View File

@ -27,14 +27,14 @@ import (
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
"github.com/meshplus/bitxhub/internal/repo"
ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
)
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string) {
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string, []string) {
var nodeKeys []crypto2.PrivKey
var privKeys []crypto.PrivateKey
var peers []string
var ids []string
port := 5001
@ -48,8 +48,9 @@ func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.Pr
id, err := peer.IDFromPublicKey(libp2pKey.GetPublic())
require.Nil(t, err)
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/%s", port, id)
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/", port)
peers = append(peers, peer)
ids = append(ids, id.String())
port++
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
@ -58,7 +59,7 @@ func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.Pr
privKeys = append(privKeys, privKey)
}
return nodeKeys, privKeys, peers
return nodeKeys, privKeys, peers, ids
}
func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, error) {
@ -75,22 +76,22 @@ func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, erro
return libp2pPrivKey, nil
}
func otherPeers(id uint64, addrs []string) map[uint64]*peer.AddrInfo {
m := make(map[uint64]*peer.AddrInfo)
func peers(id uint64, addrs []string, ids []string) []*repo.NetworkNodes {
m := make([]*repo.NetworkNodes, 0, len(addrs))
for i, addr := range addrs {
if uint64(i) == id {
continue
}
addr, _ := ma.NewMultiaddr(addr)
pAddr, _ := peer.AddrInfoFromP2pAddr(addr)
m[uint64(i)] = pAddr
m = append(m, &repo.NetworkNodes{
ID: uint64(i + 1),
Account: "",
Pid: ids[i],
Hosts: []string{addr},
})
}
return m
}
func NewSwarms(t *testing.T, peerCnt int) []*Swarm {
var swarms []*Swarm
nodeKeys, privKeys, addrs := genKeysAndConfig(t, peerCnt)
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
mockCtl := gomock.NewController(t)
mockLedger := mock_ledger.NewMockLedger(mockCtl)
@ -127,7 +128,7 @@ func NewSwarms(t *testing.T, peerCnt int) []*Swarm {
Key: &repo.Key{},
NetworkConfig: &repo.NetworkConfig{
N: uint64(peerCnt),
ID: uint64(i),
ID: uint64(i+1),
},
Certs: &repo.Certs{
NodeCertData: nodeData,
@ -141,20 +142,15 @@ func NewSwarms(t *testing.T, peerCnt int) []*Swarm {
},
},
}
var local string
id, err := peer.IDFromPublicKey(nodeKeys[i].GetPublic())
require.Nil(t, err)
if strings.HasSuffix(addrs[i], id.String()) {
idx := strings.LastIndex(addrs[i], "/p2p/")
local = addrs[i][:idx]
}
idx := strings.LastIndex(addrs[i], "/p2p/")
local := addrs[i][:idx]
repo.NetworkConfig.LocalAddr = local
repo.Key.Libp2pPrivKey = nodeKeys[i]
repo.Key.PrivKey = privKeys[i]
repo.NetworkConfig.OtherNodes = otherPeers(uint64(i), addrs)
repo.NetworkConfig.Nodes = peers(uint64(i), addrs, ids)
swarm, err := New(repo, log.NewWithModule("p2p"), mockLedger)
swarm, err := New(repo, log.NewWithModule(fmt.Sprintf("swarm%d", i)), mockLedger)
require.Nil(t, err)
err = swarm.Start()
require.Nil(t, err)
@ -214,9 +210,9 @@ func TestSwarm_Send(t *testing.T) {
}
err = retry.Retry(func(attempt uint) error {
res, err = swarms[2].Send(3, fetchAESMsg)
res, err = swarms[2].Send(4, fetchAESMsg)
if err != nil {
swarms[0].logger.Errorf(err.Error())
swarms[2].logger.Errorf(err.Error())
return err
}
return nil
@ -234,7 +230,7 @@ func TestSwarm_Send(t *testing.T) {
err = retry.Retry(func(attempt uint) error {
res, err = swarms[3].Send(1, fetchIBTPSignMsg)
if err != nil {
swarms[0].logger.Errorf(err.Error())
swarms[1].logger.Errorf(err.Error())
return err
}
return nil
@ -262,7 +258,7 @@ func TestSwarm_AsyncSend(t *testing.T) {
}
var err error
err = retry.Retry(func(attempt uint) error {
err = swarms[0].AsyncSend(2, msg)
err = swarms[0].AsyncSend(3, msg)
if err != nil {
swarms[0].logger.Errorf(err.Error())
return err

View File

@ -40,30 +40,34 @@ type Swarm struct {
cancel context.CancelFunc
}
func New(repo *repo.Repo, logger logrus.FieldLogger, ledger ledger.Ledger) (*Swarm, error) {
func New(repoConfig *repo.Repo, logger logrus.FieldLogger, ledger ledger.Ledger) (*Swarm, error) {
var protocolIDs = []string{string(protocolID)}
p2p, err := network.New(
network.WithLocalAddr(repo.NetworkConfig.LocalAddr),
network.WithPrivateKey(repo.Key.Libp2pPrivKey),
network.WithLocalAddr(repoConfig.NetworkConfig.LocalAddr),
network.WithPrivateKey(repoConfig.Key.Libp2pPrivKey),
network.WithProtocolIDs(protocolIDs),
network.WithLogger(logger),
network.WithNotify(notifiee{}),
)
if err != nil {
return nil, fmt.Errorf("create p2p: %w", err)
}
peers, err := repoConfig.NetworkConfig.GetPeers()
if err != nil {
return nil, fmt.Errorf("get peers:%w", err)
}
ctx, cancel := context.WithCancel(context.Background())
return &Swarm{
repo: repo,
repo: repoConfig,
p2p: p2p,
logger: logger,
ledger: ledger,
enablePing: repo.Config.Ping.Enable,
pingTimeout: repo.Config.Ping.Duration,
peers: repo.NetworkConfig.OtherNodes,
enablePing: repoConfig.Config.Ping.Enable,
pingTimeout: repoConfig.Config.Ping.Duration,
peers: peers,
connectedPeers: sync.Map{},
ctx: ctx,
cancel: cancel,
@ -77,7 +81,7 @@ func (swarm *Swarm) Start() error {
return err
}
for id, addr := range swarm.peers {
for id, addr := range swarm.OtherPeers() {
go func(id uint64, addr *peer.AddrInfo) {
if err := retry.Retry(func(attempt uint) error {
if err := swarm.p2p.Connect(*addr); err != nil {
@ -137,7 +141,6 @@ func (swarm *Swarm) verifyCertOrDisconnect(id uint64) error {
return nil
}
func (swarm *Swarm) Ping() {
ticker := time.NewTicker(swarm.pingTimeout)
for {
@ -211,7 +214,7 @@ func (swarm *Swarm) Send(id uint64, msg *pb.Message) (*pb.Message, error) {
func (swarm *Swarm) Broadcast(msg *pb.Message) error {
addrs := make([]string, 0, len(swarm.peers))
for _, addr := range swarm.peers {
for _, addr := range swarm.OtherPeers() {
addrs = append(addrs, addr.ID.String())
}
@ -225,8 +228,8 @@ func (swarm *Swarm) Broadcast(msg *pb.Message) error {
func (swarm *Swarm) Peers() map[uint64]*peer.AddrInfo {
m := make(map[uint64]*peer.AddrInfo)
for id, addr := range swarm.peers {
m[id] = addr
for id, node := range swarm.peers {
m[id] = node
}
return m

View File

@ -30,4 +30,12 @@ solo = false
verify = true
[order]
plugin = "plugins/raft.so"
plugin = "plugins/raft.so"
[genesis]
addresses = [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]

View File

@ -1,8 +0,0 @@
{
"addresses": [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]
}

View File

@ -1,18 +1,26 @@
id = 1 # self id
N = 4 # the number of cluster nodes
n = 4 # the number of cluster nodes
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4001/p2p/QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
id = 1
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4002/p2p/QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
id = 2
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4003/p2p/QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
id = 3
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4004/p2p/QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
id = 4
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"

View File

@ -30,4 +30,12 @@ solo = false
verify = true
[order]
plugin = "plugins/raft.so"
plugin = "plugins/raft.so"
[genesis]
addresses = [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]

View File

@ -1,8 +0,0 @@
{
"addresses": [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]
}

View File

@ -1,18 +1,26 @@
id = 2 # self id
N = 4 # the number of cluster nodes
n = 4 # the number of cluster nodes
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4001/p2p/QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
id = 1
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4002/p2p/QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
id = 2
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4003/p2p/QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
id = 3
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4004/p2p/QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
id = 4
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"

View File

@ -30,4 +30,12 @@ solo = false
verify = true
[order]
plugin = "plugins/raft3.so"
plugin = "plugins/raft3.so"
[genesis]
addresses = [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]

View File

@ -1,8 +0,0 @@
{
"addresses": [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]
}

View File

@ -1,18 +1,26 @@
id = 3 # self id
N = 4 # the number of cluster nodes
n = 4 # the number of cluster nodes
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4001/p2p/QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
id = 1
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4002/p2p/QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
id = 2
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4003/p2p/QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
id = 3
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4004/p2p/QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
id = 4
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"

View File

@ -30,4 +30,12 @@ solo = false
verify = true
[order]
plugin = "plugins/raft4.so"
plugin = "plugins/raft4.so"
[genesis]
addresses = [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]

View File

@ -1,8 +0,0 @@
{
"addresses": [
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
]
}

View File

@ -1,18 +1,26 @@
id = 4 # self id
N = 4 # the number of cluster nodes
n = 4 # the number of cluster nodes
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4001/p2p/QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
id = 1
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4002/p2p/QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
id = 2
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4003/p2p/QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
id = 3
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
[[nodes]]
addr = "/ip4/127.0.0.1/tcp/4004/p2p/QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
id = 4
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"