Merge pull request #287 from meshplus/config-change

feat(*): refactor p2p module to adapt the function of adding and deleting nodes in RBFT
This commit is contained in:
Sandy Zhou 2020-12-18 14:51:43 +08:00 committed by GitHub
commit 37588cfd26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1066 additions and 316 deletions

View File

@ -1,8 +1,6 @@
package grpc
import (
"context"
"github.com/meshplus/bitxhub-model/pb"
)
@ -16,13 +14,3 @@ func GetNetworkMeta(cbs *ChainBrokerService) (*pb.Response, error) {
Data: data,
}, nil
}
func (cbs *ChainBrokerService) DelVPNode(ctx context.Context, req *pb.DelVPNodeRequest) (*pb.Response, error) {
data, err := cbs.api.Network().DelVPNode(req.Pid)
if err != nil {
return nil, err
}
return &pb.Response{
Data: data,
}, nil
}

50
api/grpc/node.go Normal file
View File

@ -0,0 +1,50 @@
package grpc
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/meshplus/bitxhub-model/pb"
)
func (cbs *ChainBrokerService) DelVPNode(ctx context.Context, req *pb.DelVPNodeRequest) (*pb.Response, error) {
delPid := req.Pid
peersBytes,_ := cbs.api.Network().PeerInfo()
peers := make(map[uint64]*pb.VpInfo)
err := json.Unmarshal(peersBytes,&peers)
if err != nil {
return nil, err
}
var isExist bool
var delID uint64
for id, peer := range peers {
if peer.Pid == delPid {
isExist = true
delID = id
break
}
}
// If self isn't vp, rejects the rpc request and returns error.
if !isExist {
return nil, fmt.Errorf("can't find pid %s from consentor or pid illegal",delPid)
}
if err := cbs.api.Broker().OrderReady(); err != nil {
return nil, err
}
// if there're only 4 vp nodes, we don't support delete request, return error;
if len(peers) == 4 {
return nil, errors.New("can't delete node as there're only 4 vp nodes")
}
// TODO (YH): don't support delete primary node
if err := cbs.api.Broker().DelVPNode(delID); err != nil {
return nil, err
}
return &pb.Response {
Data: nil,
},nil
}

View File

@ -25,6 +25,7 @@ var clientCMD = cli.Command{
receiptCMD(),
txCMD(),
validatorsCMD(),
delVPNodeCMD(),
},
}

View File

@ -39,3 +39,31 @@ func getValidators(ctx *cli.Context) error {
return nil
}
func delVPNodeCMD() cli.Command {
return cli.Command{
Name: "delVPNode",
Usage: "delete a vp node",
Action: delVPNode,
}
}
func delVPNode(ctx *cli.Context) error {
if ctx.NArg() < 1 {
return fmt.Errorf("please input pid")
}
url, err := getURL(ctx, "delvpnode/"+ctx.Args().Get(0))
if err != nil {
return err
}
// TODO (FBZ): change to httpPost
data, err := httpGet(url)
if err != nil {
return err
}
fmt.Println(string(data))
return nil
}

View File

@ -1,26 +1,27 @@
id = 1
n = 4
id = 1 # self id
n = 4 # the number of vp nodes
new = false # track whether the node is a new node
[[nodes]]
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
hosts = ["/ip4/127.0.0.1/tcp/4001/p2p/"]
id = 1
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
[[nodes]]
account = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
hosts = ["/ip4/127.0.0.1/tcp/4002/p2p/"]
id = 2
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
[[nodes]]
account = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
hosts = ["/ip4/127.0.0.1/tcp/4003/p2p/"]
id = 3
pid = "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL"
pid = "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS"
[[nodes]]
account = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
hosts = ["/ip4/127.0.0.1/tcp/4004/p2p/"]
id = 4
pid = "QmbmD1kzdsxRiawxu7bRrteDgW1ituXupR8GH6E2EUAHY4"
pid = "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy"

View File

@ -1,9 +1,9 @@
[raft]
tick_timeout = "0.1s" # TickTimeout is the internal logical clock for the Node by a single tick, Election timeouts and heartbeat timeouts are in units of ticks.
election_tick = 10 # ElectionTick is the number of Node.Tick invocations that must pass between elections.
heartbeat_tick = 1 # HeartbeatTick is the number of Node.Tick invocations that must pass between heartbeats.
heartbeat_tick = 1 # HeartbeatTick is the number of Node.Tick invocations that must pass between heartbeats.
max_size_per_msg = 1048576 # 1024*1024, MaxSizePerMsg limits the max size of each append message.
max_inflight_msgs = 500 # MaxInflightMsgs limits the max number of in-flight append messages during optimistic replication phase.
max_inflight_msgs = 500 # MaxInflightMsgs limits the max number of in-flight append messages during optimistic replication phase.
check_quorum = true # Leader steps down when quorum is not active for an electionTimeout.
pre_vote = true # PreVote prevents reconnected node from disturbing network.
disable_proposal_forwarding = true # This prevents blocks from being accidentally proposed by followers.
@ -13,17 +13,18 @@ disable_proposal_forwarding = true # This prevents blocks from being accidentall
pool_size = 50000 # How many transactions could the txPool stores in total.
tx_slice_size = 10 # How many transactions should the node broadcast at once
batch_tick = "0.3s" # Block packaging time period.
batch_tick = "0.3s" # Block packaging time period.
tx_slice_timeout = "0.1s" # Node broadcasts transactions if there are cached transactions, although set_size isn't reached yet
fetch_timeout = "3s" # How long to wait before fetching missing transactions finished
[rbft] #RBFT configurations
set_size = 25 # How many transactions should the node broadcast at once
set_size = 25 # How many transactions should the node broadcast at once
batch_size = 500 # How many transactions should the primary pack before sending pre-prepare
pool_size = 50000 # How many transactions could the txPool stores in total
vc_period = 0 # After how many checkpoint periods( Blocks = 10 * vcperiod ) the primary gets cycled automatically. ( Set 0 to disable )
check_interval = "3m" # interval of the check loop
tolerance_time = "5m" # The max tolerance time duration (in seconds) of out-of-date
check_interval = "3m" # interval of the check loop
tolerance_time = "5m" # The max tolerance time duration (in seconds) of out-of-date
batch_mem_limit = false # Indicates whether limit batch mem size or not
batch_max_mem = 10000 # The max memory size of one batch
@ -39,4 +40,4 @@ batch_max_mem = 10000 # The max memory size of one batch
resend_viewchange = "10s" # How long to wait for a view change quorum before resending (the same) view change
clean_viewchange = "60s" # How long to clean out-of-data view change message
update = "4s" # How long may a update-n take
set = "0.1s" # Node broadcasts transactions if there are cached transactions, although set_size isn't reached yet
set = "0.1s" # Node broadcasts transactions if there are cached transactions, although set_size isn't reached yet

View File

@ -20,7 +20,6 @@ import (
"github.com/meshplus/bitxhub/internal/router"
"github.com/meshplus/bitxhub/internal/storages"
"github.com/meshplus/bitxhub/pkg/order"
"github.com/meshplus/bitxhub/pkg/order/etcdraft"
"github.com/meshplus/bitxhub/pkg/peermgr"
"github.com/sirupsen/logrus"
)
@ -36,21 +35,21 @@ type BitXHub struct {
repo *repo.Repo
logger logrus.FieldLogger
ctx context.Context
cancel context.CancelFunc
Ctx context.Context
Cancel context.CancelFunc
}
func NewBitXHub(rep *repo.Repo) (*BitXHub, error) {
repoRoot := rep.Config.RepoRoot
bxh, err := generateBitXHubWithoutOrder(rep)
bxh, err := GenerateBitXHubWithoutOrder(rep)
if err != nil {
return nil, err
}
chainMeta := bxh.Ledger.GetChainMeta()
m := rep.NetworkConfig.GetVpAccount()
m := rep.NetworkConfig.GetVpInfos()
order, err := orderplg.New(
order.WithRepoRoot(repoRoot),
@ -58,6 +57,7 @@ func NewBitXHub(rep *repo.Repo) (*BitXHub, error) {
order.WithPluginPath(rep.Config.Plugin),
order.WithNodes(m),
order.WithID(rep.NetworkConfig.ID),
order.WithIsNew(rep.NetworkConfig.IsNew),
order.WithPeerManager(bxh.PeerMgr),
order.WithLogger(loggers.Logger(loggers.Order)),
order.WithApplied(chainMeta.Height),
@ -77,15 +77,15 @@ func NewBitXHub(rep *repo.Repo) (*BitXHub, error) {
ctx, cancel := context.WithCancel(context.Background())
bxh.ctx = ctx
bxh.cancel = cancel
bxh.Ctx = ctx
bxh.Cancel = cancel
bxh.Order = order
bxh.Router = r
return bxh, nil
}
func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
func GenerateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
repoRoot := rep.Config.RepoRoot
logger := loggers.Logger(loggers.App)
@ -156,52 +156,6 @@ func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
}, nil
}
func NewTesterBitXHub(rep *repo.Repo) (*BitXHub, error) {
repoRoot := rep.Config.RepoRoot
bxh, err := generateBitXHubWithoutOrder(rep)
if err != nil {
return nil, err
}
chainMeta := bxh.Ledger.GetChainMeta()
m := rep.NetworkConfig.GetVpAccount()
order, err := etcdraft.NewNode(
order.WithRepoRoot(repoRoot),
order.WithStoragePath(repo.GetStoragePath(repoRoot, "order")),
order.WithPluginPath(rep.Config.Plugin),
order.WithNodes(m),
order.WithID(rep.NetworkConfig.ID),
order.WithPeerManager(bxh.PeerMgr),
order.WithLogger(loggers.Logger(loggers.Order)),
order.WithApplied(chainMeta.Height),
order.WithDigest(chainMeta.BlockHash.String()),
order.WithGetChainMetaFunc(bxh.Ledger.GetChainMeta),
order.WithGetTransactionFunc(bxh.Ledger.GetTransaction),
order.WithGetBlockByHeightFunc(bxh.Ledger.GetBlock),
)
if err != nil {
return nil, err
}
r, err := router.New(loggers.Logger(loggers.Router), rep, bxh.Ledger, bxh.PeerMgr, order.Quorum())
if err != nil {
return nil, fmt.Errorf("create InterchainRouter: %w", err)
}
ctx, cancel := context.WithCancel(context.Background())
bxh.ctx = ctx
bxh.cancel = cancel
bxh.Order = order
bxh.Router = r
return bxh, nil
}
func (bxh *BitXHub) Start() error {
if err := bxh.raiseUlimit(2048); err != nil {
@ -258,7 +212,7 @@ func (bxh *BitXHub) Stop() error {
bxh.Order.Stop()
bxh.cancel()
bxh.Cancel()
bxh.logger.Info("Bitxhub stopped")

View File

@ -19,7 +19,7 @@ func (bxh *BitXHub) start() {
"count": len(block.Transactions),
}).Info("Generated block")
bxh.BlockExecutor.ExecuteBlock(block)
case <-bxh.ctx.Done():
case <-bxh.Ctx.Done():
return
}
}
@ -46,7 +46,7 @@ func (bxh *BitXHub) listenEvent() {
bxh.logger.Error(err)
}
}()
case <-bxh.ctx.Done():
case <-bxh.Ctx.Done():
return
}
}

View File

@ -40,13 +40,15 @@ type BrokerAPI interface {
// OrderReady
OrderReady() error
// DelVPNode delete a vp node by given id.
DelVPNode(delID uint64) error
FetchSignsFromOtherPeers(content string, typ pb.GetMultiSignsRequest_Type) map[string][]byte
GetSign(content string, typ pb.GetMultiSignsRequest_Type) (string, []byte, error)
}
type NetworkAPI interface {
PeerInfo() ([]byte, error)
DelVPNode(pid string) ([]byte, error)
}
type ChainAPI interface {

View File

@ -279,3 +279,7 @@ func (b *BrokerAPI) getSign(content string) (string, []byte, error) {
func (b BrokerAPI) GetPendingNonceByAccount(account string) uint64 {
return b.bxh.Order.GetPendingNonceByAccount(account)
}
func (b BrokerAPI) DelVPNode(delID uint64) error {
return b.bxh.Order.DelNode(delID)
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"path/filepath"
"sort"
"strings"
"github.com/libp2p/go-libp2p-core/crypto"
@ -21,6 +22,7 @@ import (
type NetworkConfig struct {
ID uint64 `toml:"id" json:"id"`
N uint64 `toml:"n" json:"n"`
IsNew bool `toml:"new" json:"new"`
LocalAddr string `toml:"local_addr, omitempty" json:"local_addr"`
Nodes []*NetworkNodes `toml:"nodes" json:"nodes"`
Genesis Genesis `toml:"genesis, omitempty" json:"genesis"`
@ -71,17 +73,18 @@ func loadNetworkConfig(repoRoot string, genesis Genesis) (*NetworkConfig, error)
}
// GetVpInfos gets vp info from network config
func (config *NetworkConfig) GetVpInfos() []*pb.VpInfo {
vpGenesisInfos := make([]*pb.VpInfo, 0, len(config.Nodes))
func (config *NetworkConfig) GetVpInfos() map[uint64]*pb.VpInfo {
vpNodes := make(map[uint64]*pb.VpInfo)
for _, node := range config.Nodes {
vpGenesisInfos = append(vpGenesisInfos, &pb.VpInfo{
vpInfo := &pb.VpInfo{
Id: node.ID,
Pid: node.Pid,
Account: node.Account,
Hosts: node.Hosts,
})
}
vpNodes[node.ID] = vpInfo
}
return vpGenesisInfos
return vpNodes
}
// GetVpGenesisAccount gets genesis address from network config
@ -102,8 +105,8 @@ func (config *NetworkConfig) GetVpAccount() map[uint64]types.Address {
return m
}
// GetPeers gets all peers from network config
func (config *NetworkConfig) GetPeers() (map[uint64]*peer.AddrInfo, error) {
// GetNetworkPeers gets all peers from network config
func (config *NetworkConfig) GetNetworkPeers() (map[uint64]*peer.AddrInfo, error) {
peers := make(map[uint64]*peer.AddrInfo)
for _, node := range config.Nodes {
if len(node.Hosts) == 0 {
@ -130,7 +133,7 @@ func (config *NetworkConfig) GetPeers() (map[uint64]*peer.AddrInfo, error) {
return peers, nil
}
func RewriteNetworkConfig(repoRoot string, infos []*pb.VpInfo) error {
func RewriteNetworkConfig(repoRoot string, infos map[uint64]*pb.VpInfo, isNew bool) error {
networkConfig := &NetworkConfig{}
v := viper.New()
v.SetConfigFile(filepath.Join(repoRoot, "network.toml"))
@ -143,7 +146,14 @@ func RewriteNetworkConfig(repoRoot string, infos []*pb.VpInfo) error {
}
nodes := make([]*NetworkNodes, 0, len(infos))
routers := make([]*pb.VpInfo, 0, len(nodes))
for _, info := range infos {
routers = append(routers, info)
}
sort.Slice(routers, func(i, j int) bool {
return routers[i].Id < routers[j].Id
})
for _, info := range routers {
node := &NetworkNodes{
ID: info.Id,
Pid: info.Pid,
@ -154,6 +164,7 @@ func RewriteNetworkConfig(repoRoot string, infos []*pb.VpInfo) error {
}
networkConfig.Nodes = nodes
networkConfig.N = uint64(len(nodes))
networkConfig.IsNew = isNew
data, err := toml.Marshal(*networkConfig)
if err != nil {
return err
@ -188,16 +199,3 @@ func GetPidFromPrivFile(privPath string) (string, error) {
return pid.String(), nil
}
// MultiaddrToPeerID .
func MultiaddrToPeerID(multiAddr string) (string, error) {
maddri, err := ma.NewMultiaddr(multiAddr)
if err != nil {
return "", err
}
_, PeerID := peer.SplitAddr(maddri)
if PeerID == "" {
return "", err
}
return PeerID.String(), nil
}

View File

@ -14,7 +14,7 @@ func TestNetworkConfig(t *testing.T) {
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"}})
require.Nil(t, err)
peers, err := cfg.GetPeers()
peers, err := cfg.GetNetworkPeers()
require.Nil(t, err)
require.Equal(t, 4, len(peers))
@ -29,41 +29,33 @@ func TestNetworkConfig(t *testing.T) {
}
func TestRewriteNetworkConfig(t *testing.T) {
infos := make([]*pb.VpInfo, 0)
infos := make(map[uint64]*pb.VpInfo, 0)
{
infos = append(infos, &pb.VpInfo{
infos[1] = &pb.VpInfo{
Id: 1,
Hosts: []string{"/ip4/127.0.0.1/tcp/4001/p2p/"},
Pid: "QmQUcDYCtqbpn5Nhaw4FAGxQaSSNvdWfAFcpQT9SPiezbS",
Account: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
})
infos = append(infos, &pb.VpInfo{
}
infos[2] = &pb.VpInfo{
Id: 2,
Hosts: []string{"/ip4/127.0.0.1/tcp/4002/p2p/"},
Pid: "QmQW3bFn8XX1t4W14Pmn37bPJUpUVBrBjnPuBZwPog3Qdy",
Account: "0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
})
infos = append(infos, &pb.VpInfo{
}
infos[3] = &pb.VpInfo{
Id: 3,
Hosts: []string{"/ip4/127.0.0.1/tcp/4003/p2p/"},
Pid: "QmXi58fp9ZczF3Z5iz1yXAez3Hy5NYo1R8STHWKEM9XnTL",
Account: "0x97c8B516D19edBf575D72a172Af7F418BE498C37",
})
infos = append(infos, &pb.VpInfo{
}
infos[4] = &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])
err := RewriteNetworkConfig("./testdata", infos, false)
require.Nil(t, err)
}

View File

@ -1,5 +1,6 @@
id = 1
n = 4
new = false
[[nodes]]
account = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"

View File

@ -12,13 +12,14 @@ import (
type Config struct {
ID uint64
IsNew bool
RepoRoot string
StoragePath string
PluginPath string
PeerMgr peermgr.PeerManager
PrivKey crypto.PrivateKey
Logger logrus.FieldLogger
Nodes map[uint64]types.Address
Nodes map[uint64]*pb.VpInfo
Applied uint64
Digest string
GetTransactionFunc func(hash *types.Hash) (*pb.Transaction, error)
@ -34,6 +35,12 @@ func WithID(id uint64) Option {
}
}
func WithIsNew(isNew bool) Option {
return func(config *Config) {
config.IsNew = isNew
}
}
func WithRepoRoot(path string) Option {
return func(config *Config) {
config.RepoRoot = path
@ -70,7 +77,7 @@ func WithLogger(logger logrus.FieldLogger) Option {
}
}
func WithNodes(nodes map[uint64]types.Address) Option {
func WithNodes(nodes map[uint64]*pb.VpInfo) Option {
return func(config *Config) {
config.Nodes = nodes
}

View File

@ -58,6 +58,7 @@ type Node struct {
justElected bool
isRestart bool
// TODO (YH): refactor
ctx context.Context // context
haltC chan struct{} // exit signal
@ -611,7 +612,11 @@ func GenerateRaftPeers(config *order.Config) ([]raft.Peer, error) {
for _, id := range idSlice {
addr := nodes[id]
peers = append(peers, raft.Peer{ID: id, Context: addr.Bytes()})
addBytes,err := addr.Marshal()
if err != nil {
return nil, err
}
peers = append(peers, raft.Peer{ID: id, Context: addBytes})
}
return peers, nil
}
@ -654,6 +659,12 @@ func (n *Node) writeAppliedIndex(index uint64) {
n.storage.Put(appliedDbKey, buf)
}
// GetPendingNonceByAccount gets pending nonce by given account.
func (n *Node) GetPendingNonceByAccount(account string) uint64 {
return n.mempool.GetPendingNonceByAccount(account)
}
// DelNode sends a delete vp request by given id.
func (n *Node) DelNode(delID uint64) error {
return nil
}

View File

@ -38,9 +38,12 @@ func TestNode_Start(t *testing.T) {
defer os.RemoveAll(repoRoot)
var ID uint64 = 1
nodes := make(map[uint64]types.Address)
hash := types.NewAddressByStr("000000000000000000000000000000000000000a")
nodes[ID] = *hash
nodes := make(map[uint64]*pb.VpInfo)
vpInfo := &pb.VpInfo{
Id: ID,
Account: types.NewAddressByStr("000000000000000000000000000000000000000a").String(),
}
nodes[ID] = vpInfo
fileData, err := ioutil.ReadFile("../../../config/order.toml")
require.Nil(t, err)
err = ioutil.WriteFile(filepath.Join(repoRoot, "order.toml"), fileData, 0644)
@ -49,7 +52,7 @@ func TestNode_Start(t *testing.T) {
mockCtl := gomock.NewController(t)
mockPeermgr := mock_peermgr.NewMockPeerManager(mockCtl)
peers := make(map[uint64]*peer.AddrInfo)
peers := make(map[uint64]*pb.VpInfo)
mockPeermgr.EXPECT().Peers().Return(peers).AnyTimes()
order, err := NewNode(
@ -229,9 +232,9 @@ func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, erro
return libp2pPrivKey, nil
}
func newSwarms(t *testing.T, peerCnt int) ([]*peermgr.Swarm, map[uint64]types.Address) {
func newSwarms(t *testing.T, peerCnt int) ([]*peermgr.Swarm, map[uint64]*pb.VpInfo) {
var swarms []*peermgr.Swarm
nodes := make(map[uint64]types.Address)
nodes := make(map[uint64]*pb.VpInfo)
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
mockCtl := gomock.NewController(t)
mockLedger := mock_ledger.NewMockLedger(mockCtl)
@ -276,7 +279,11 @@ func newSwarms(t *testing.T, peerCnt int) ([]*peermgr.Swarm, map[uint64]types.Ad
address, err := privKeys[i].PublicKey().Address()
require.Nil(t, err)
nodes[uint64(ID)] = *address
vpInfo := &pb.VpInfo{
Id: uint64(ID),
Account: address.String(),
}
nodes[uint64(ID)] = vpInfo
swarm, err := peermgr.New(repo, log.NewWithModule("p2p"), mockLedger)
require.Nil(t, err)
err = swarm.Start()

View File

@ -7,6 +7,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/event"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/crypto/asym"
"github.com/meshplus/bitxhub-kit/log"
@ -16,8 +17,6 @@ import (
"github.com/meshplus/bitxhub/internal/model/events"
raftproto "github.com/meshplus/bitxhub/pkg/order/etcdraft/proto"
network "github.com/meshplus/go-lightp2p"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/stretchr/testify/mock"
)
@ -126,15 +125,24 @@ func (mpm *mockPeerMgr) Send(uint64, *pb.Message) (*pb.Message, error) {
return nil, nil
}
func (mpm *mockPeerMgr) Peers() map[uint64]*peer.AddrInfo {
peers := make(map[uint64]*peer.AddrInfo, 3)
var id1 peer.ID
id1 = "peer1"
peers[0] = &peer.AddrInfo{ID: id1}
func (mpm *mockPeerMgr)AddNode(newNodeID uint64, vpInfo *pb.VpInfo) {}
func (mpm *mockPeerMgr)DelNode(delID uint64){}
func (mpm *mockPeerMgr)UpdateRouter(vpInfos map[uint64]*pb.VpInfo, isNew bool) bool {
return false
}
func (mpm *mockPeerMgr)Disconnect(vpInfos map[uint64]*pb.VpInfo) {}
func (mpm *mockPeerMgr) Peers() map[uint64]*pb.VpInfo {
peers := make(map[uint64]*pb.VpInfo, 3)
id1 := "peer1"
peers[0] = &pb.VpInfo{Pid: id1}
id1 = "peer2"
peers[1] = &peer.AddrInfo{ID: id1}
peers[1] = &pb.VpInfo{Pid: id1}
id1 = "peer3"
peers[2] = &peer.AddrInfo{ID: id1}
peers[2] = &pb.VpInfo{Pid: id1}
return peers
}

View File

@ -21,7 +21,7 @@ func (mpi *mempoolImpl) broadcast(m *pb.Message) {
func (mpi *mempoolImpl) unicast(to uint64, m *pb.Message) {
go func() {
if err := mpi.peerMgr.AsyncSend(to, m); err != nil {
mpi.logger.Error("Send message to peer %d failed, err: %s", to, err.Error())
mpi.logger.Warningf("Send message to peer %d failed, err: %s", to, err.Error())
}
}()
}

View File

@ -2,7 +2,6 @@ package order
import (
"context"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
)
@ -35,4 +34,7 @@ type Order interface {
// GetPendingNonce will return the latest pending nonce of a given account
GetPendingNonceByAccount(account string) uint64
// DelNode sends a delete vp request by given id.
DelNode(delID uint64) error
}

View File

@ -9,7 +9,6 @@ import (
"time"
"github.com/golang/mock/gomock"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/meshplus/bitxhub-kit/storage/leveldb"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
@ -57,6 +56,10 @@ func (n *Node) GetPendingNonceByAccount(account string) uint64 {
return n.mempool.GetPendingNonceByAccount(account)
}
func (n *Node) DelNode(delID uint64) error {
return nil
}
func (n *Node) Prepare(tx *pb.Transaction) error {
if err := n.Ready(); err != nil {
return err
@ -110,7 +113,7 @@ func NewNode(opts ...order.Option) (order.Order, error) {
mockCtl := gomock.NewController(&testing.T{})
peerMgr := mock_peermgr.NewMockPeerManager(mockCtl)
peerMgr.EXPECT().Peers().Return(map[uint64]*peer.AddrInfo{}).AnyTimes()
peerMgr.EXPECT().Peers().Return(map[uint64]*pb.VpInfo{}).AnyTimes()
memConfig, err := generateMempoolConfig(config.RepoRoot)
mempoolConf := &mempool.Config{
ID: config.ID,

View File

@ -8,7 +8,6 @@ import (
"time"
"github.com/golang/mock/gomock"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/crypto/asym"
"github.com/meshplus/bitxhub-kit/log"
@ -36,12 +35,15 @@ func TestNode_Start(t *testing.T) {
mockCtl := gomock.NewController(t)
mockPeermgr := mock_peermgr.NewMockPeerManager(mockCtl)
peers := make(map[uint64]*peer.AddrInfo)
peers := make(map[uint64]*pb.VpInfo)
mockPeermgr.EXPECT().Peers().Return(peers).AnyTimes()
nodes := make(map[uint64]types.Address)
hash := types.NewAddressByStr("000000000000000000000000000000000000000a")
nodes[1] = *hash
nodes := make(map[uint64]*pb.VpInfo)
vpInfo := & pb.VpInfo{
Id: uint64(1),
Account: types.NewAddressByStr("000000000000000000000000000000000000000a").String(),
}
nodes[1] = vpInfo
order, err := NewNode(
order.WithRepoRoot(repoRoot),

View File

@ -123,10 +123,10 @@ func (mr *MockPeerManagerMockRecorder) Broadcast(arg0 interface{}) *gomock.Call
}
// Peers mocks base method
func (m *MockPeerManager) Peers() map[uint64]*peer.AddrInfo {
func (m *MockPeerManager) Peers() map[uint64]*pb.VpInfo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Peers")
ret0, _ := ret[0].(map[uint64]*peer.AddrInfo)
ret0, _ := ret[0].(map[uint64]*pb.VpInfo)
return ret0
}
@ -163,3 +163,53 @@ func (mr *MockPeerManagerMockRecorder) SubscribeOrderMessage(ch interface{}) *go
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeOrderMessage", reflect.TypeOf((*MockPeerManager)(nil).SubscribeOrderMessage), ch)
}
// AddNode mocks base method
func (m *MockPeerManager) AddNode(newNodeID uint64, vpInfo *pb.VpInfo) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "AddNode", newNodeID, vpInfo)
}
// AddNode indicates an expected call of AddNode
func (mr *MockPeerManagerMockRecorder) AddNode(newNodeID, vpInfo interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNode", reflect.TypeOf((*MockPeerManager)(nil).AddNode), newNodeID, vpInfo)
}
// DelNode mocks base method
func (m *MockPeerManager) DelNode(delID uint64) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "DelNode", delID)
}
// DelNode indicates an expected call of DelNode
func (mr *MockPeerManagerMockRecorder) DelNode(delID interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelNode", reflect.TypeOf((*MockPeerManager)(nil).DelNode), delID)
}
// UpdateRouter mocks base method
func (m *MockPeerManager) UpdateRouter(vpInfos map[uint64]*pb.VpInfo, isNew bool) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateRouter", vpInfos, isNew)
ret0, _ := ret[0].(bool)
return ret0
}
// UpdateRouter indicates an expected call of UpdateRouter
func (mr *MockPeerManagerMockRecorder) UpdateRouter(vpInfos, isNew interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRouter", reflect.TypeOf((*MockPeerManager)(nil).UpdateRouter), vpInfos, isNew)
}
// Disconnect mocks base method
func (m *MockPeerManager) Disconnect(vpInfos map[uint64]*pb.VpInfo) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Disconnect", vpInfos)
}
// Disconnect indicates an expected call of Disconnect
func (mr *MockPeerManagerMockRecorder) Disconnect(vpInfos interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Disconnect", reflect.TypeOf((*MockPeerManager)(nil).Disconnect), vpInfos)
}

View File

@ -1,29 +1,68 @@
package peermgr
import (
"fmt"
"github.com/libp2p/go-libp2p-core/network"
"github.com/meshplus/bitxhub-model/pb"
ma "github.com/multiformats/go-multiaddr"
"github.com/sirupsen/logrus"
"sync"
)
type notifiee struct {
peers map[uint64]*pb.VpInfo
// TODO (Peer): keep access goroutine safety
newPeer string
mu sync.RWMutex
logger logrus.FieldLogger
}
func (n notifiee) Listen(network network.Network, multiaddr ma.Multiaddr) {
func newNotifiee(peers map[uint64]*pb.VpInfo, logger logrus.FieldLogger) *notifiee {
return &notifiee{
peers: peers,
logger: logger,
}
}
func (n notifiee) ListenClose(network network.Network, multiaddr ma.Multiaddr) {
func (n *notifiee) Listen(network network.Network, multiaddr ma.Multiaddr) {
}
func (n notifiee) Connected(network network.Network, conn network.Conn) {
fmt.Println("new connect:" + conn.RemotePeer().String())
func (n *notifiee) ListenClose(network network.Network, multiaddr ma.Multiaddr) {
}
func (n notifiee) Disconnected(network network.Network, conn network.Conn) {
func (n *notifiee) Connected(network network.Network, conn network.Conn) {
peers := n.getPeers()
newAddr := conn.RemotePeer().String()
// check if the newAddr has already in peers.
for _, p := range peers {
if p.Pid == newAddr {
return
}
}
if n.newPeer == "" {
n.newPeer = newAddr
n.logger.Infof("Updating notifiee newPeer %s", newAddr)
return
}
n.logger.Infof("The newPeer %s is not nil, skip the new addr %s", n.newPeer, newAddr)
}
func (n notifiee) OpenedStream(network network.Network, stream network.Stream) {
func (n *notifiee) Disconnected(network network.Network, conn network.Conn) {
}
func (n notifiee) ClosedStream(network network.Network, stream network.Stream) {
func (n *notifiee) OpenedStream(network network.Network, stream network.Stream) {
}
func (n *notifiee) ClosedStream(network network.Network, stream network.Stream) {
}
func (n *notifiee) getPeers() map[uint64]*pb.VpInfo {
n.mu.RLock()
defer n.mu.RUnlock()
return n.peers
}
func (n *notifiee) setPeers(peers map[uint64]*pb.VpInfo) {
n.mu.Lock()
defer n.mu.Unlock()
n.peers = peers
}

View File

@ -29,11 +29,23 @@ type PeerManager interface {
Broadcast(*pb.Message) error
// Peers
Peers() map[uint64]*peer.AddrInfo
Peers() map[uint64]*pb.VpInfo
// OtherPeers
OtherPeers() map[uint64]*peer.AddrInfo
// SubscribeOrderMessage
SubscribeOrderMessage(ch chan<- events.OrderMessageEvent) event.Subscription
// AddNode adds a vp peer.
AddNode(newNodeID uint64, vpInfo *pb.VpInfo)
// DelNode deletes a vp peer.
DelNode(delID uint64)
// UpdateRouter update the local router to quorum router.
UpdateRouter (vpInfos map[uint64]*pb.VpInfo, isNew bool) bool
// Disconnect disconnect with all vp peers.
Disconnect(vpInfos map[uint64]*pb.VpInfo)
}

View File

@ -3,6 +3,7 @@ package peermgr
import (
"context"
"fmt"
ma "github.com/multiformats/go-multiaddr"
"sync"
"time"
@ -26,11 +27,16 @@ const (
)
type Swarm struct {
repo *repo.Repo
p2p network.Network
logger logrus.FieldLogger
peers map[uint64]*peer.AddrInfo
connectedPeers sync.Map
repo *repo.Repo
localID uint64
p2p network.Network
logger logrus.FieldLogger
routers map[uint64]*pb.VpInfo // trace the vp nodes
multiAddrs map[uint64]*peer.AddrInfo
connectedPeers sync.Map
notifiee *notifiee
ledger ledger.Ledger
orderMessageFeed event.Feed
enablePing bool
@ -42,33 +48,54 @@ type Swarm struct {
func New(repoConfig *repo.Repo, logger logrus.FieldLogger, ledger ledger.Ledger) (*Swarm, error) {
var protocolIDs = []string{string(protocolID)}
// init peers with ips and hosts
routers := repoConfig.NetworkConfig.GetVpInfos()
bootstrap := make([]string, 0)
for _, p := range routers {
if p.Id == repoConfig.NetworkConfig.ID {
continue
}
addr := fmt.Sprintf("%s%s", p.Hosts[0], p.Pid)
bootstrap = append(bootstrap, addr)
}
multiAddrs := make(map[uint64]*peer.AddrInfo)
p2pPeers, _ := repoConfig.NetworkConfig.GetNetworkPeers()
for id, node := range p2pPeers {
if id == repoConfig.NetworkConfig.ID {
continue
}
multiAddrs[id] = node
}
notifiee := newNotifiee(routers, logger)
p2p, err := network.New(
network.WithLocalAddr(repoConfig.NetworkConfig.LocalAddr),
network.WithPrivateKey(repoConfig.Key.Libp2pPrivKey),
network.WithProtocolIDs(protocolIDs),
network.WithLogger(logger),
network.WithNotify(notifiee{}),
// enable discovery
network.WithBootstrap(bootstrap),
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: repoConfig,
localID: repoConfig.NetworkConfig.ID,
p2p: p2p,
logger: logger,
ledger: ledger,
enablePing: repoConfig.Config.Ping.Enable,
pingTimeout: repoConfig.Config.Ping.Duration,
peers: peers,
routers: routers,
multiAddrs: multiAddrs,
connectedPeers: sync.Map{},
notifiee: notifiee,
ctx: ctx,
cancel: cancel,
}, nil
@ -81,9 +108,15 @@ func (swarm *Swarm) Start() error {
return err
}
for id, addr := range swarm.OtherPeers() {
for id, addr := range swarm.multiAddrs {
go func(id uint64, addr *peer.AddrInfo) {
if err := retry.Retry(func(attempt uint) error {
// for restart node, after updating the routing table, some nodes may not exist in routing table
routers := swarm.notifiee.getPeers()
if _, ok := routers[id]; !ok {
swarm.logger.Infof("Can't find node %d from routing table, stopping connect", id)
return nil
}
if err := swarm.p2p.Connect(*addr); err != nil {
swarm.logger.WithFields(logrus.Fields{
"node": id,
@ -127,16 +160,14 @@ func (swarm *Swarm) Start() error {
func (swarm *Swarm) Stop() error {
swarm.cancel()
return nil
}
func (swarm *Swarm) verifyCertOrDisconnect(id uint64) error {
if err := swarm.verifyCert(id); err != nil {
if err = swarm.p2p.Disconnect(swarm.peers[id].ID.String()); err != nil {
if err = swarm.p2p.Disconnect(swarm.routers[id].Pid); err != nil {
return err
}
return err
}
return nil
}
@ -161,13 +192,19 @@ func (swarm *Swarm) Ping() {
}
return true
})
swarm.logger.WithFields(fields).Warning("ping time")
swarm.logger.WithFields(fields).Info("ping time")
case <-swarm.ctx.Done():
return
}
}
}
func (swarm *Swarm) AsyncSend(id uint64, msg *pb.Message) error {
if err := swarm.checkID(id); err != nil {
var (
addr string
err error
)
if addr, err = swarm.findPeer(id); err != nil {
return fmt.Errorf("p2p send: %w", err)
}
@ -175,7 +212,6 @@ func (swarm *Swarm) AsyncSend(id uint64, msg *pb.Message) error {
if err != nil {
return err
}
addr := swarm.peers[id].ID.String()
return swarm.p2p.AsyncSend(addr, data)
}
@ -189,7 +225,11 @@ func (swarm *Swarm) SendWithStream(s network.Stream, msg *pb.Message) error {
}
func (swarm *Swarm) Send(id uint64, msg *pb.Message) (*pb.Message, error) {
if err := swarm.checkID(id); err != nil {
var (
addr string
err error
)
if addr, err = swarm.findPeer(id); err != nil {
return nil, fmt.Errorf("check id: %w", err)
}
@ -198,7 +238,6 @@ func (swarm *Swarm) Send(id uint64, msg *pb.Message) (*pb.Message, error) {
return nil, err
}
addr := swarm.peers[id].ID.String()
ret, err := swarm.p2p.Send(addr, data)
if err != nil {
return nil, fmt.Errorf("sync send: %w", err)
@ -213,9 +252,19 @@ 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.OtherPeers() {
addrs = append(addrs, addr.ID.String())
addrs := make([]string, 0, len(swarm.routers))
for _, router := range swarm.routers {
if router.Id == swarm.localID {
continue
}
addrs = append(addrs, router.Pid)
}
// if we are in adding node but hasn't finished updateN, new node hash will be temporarily recorded
// in swarm.notifiee.newPeer.
if swarm.notifiee.newPeer != "" {
swarm.logger.Debugf("Broadcast to new peer %s", swarm.notifiee.newPeer)
addrs = append(addrs, swarm.notifiee.newPeer)
}
data, err := msg.Marshal()
@ -226,21 +275,22 @@ func (swarm *Swarm) Broadcast(msg *pb.Message) error {
return swarm.p2p.Broadcast(addrs, data)
}
func (swarm *Swarm) Peers() map[uint64]*peer.AddrInfo {
m := make(map[uint64]*peer.AddrInfo)
for id, node := range swarm.peers {
m[id] = node
}
return m
func (swarm *Swarm) Peers() map[uint64]*pb.VpInfo {
return swarm.notifiee.getPeers()
}
func (swarm *Swarm) OtherPeers() map[uint64]*peer.AddrInfo {
m := swarm.Peers()
if swarm.repo != nil {
delete(m, swarm.repo.NetworkConfig.ID)
addrInfos := make(map[uint64]*peer.AddrInfo)
for _, node := range swarm.notifiee.getPeers() {
if node.Id == swarm.localID {
continue
}
addrInfo := &peer.AddrInfo{
ID: peer.ID(node.Pid),
}
addrInfos[node.Id] = addrInfo
}
return m
return addrInfos
}
func (swarm *Swarm) SubscribeOrderMessage(ch chan<- events.OrderMessageEvent) event.Subscription {
@ -248,7 +298,7 @@ func (swarm *Swarm) SubscribeOrderMessage(ch chan<- events.OrderMessageEvent) ev
}
func (swarm *Swarm) verifyCert(id uint64) error {
if err := swarm.checkID(id); err != nil {
if _, err := swarm.findPeer(id); err != nil {
return fmt.Errorf("check id: %w", err)
}
@ -280,18 +330,163 @@ func (swarm *Swarm) verifyCert(id uint64) error {
return fmt.Errorf("verify certs: %w", err)
}
err = swarm.p2p.Disconnect(swarm.peers[id].ID.String())
err = swarm.p2p.Disconnect(swarm.routers[id].Pid)
if err != nil {
return fmt.Errorf("disconnect peer: %w", err)
}
return nil
}
func (swarm *Swarm) checkID(id uint64) error {
if swarm.peers[id] == nil {
return fmt.Errorf("wrong id: %d", id)
func (swarm *Swarm) findPeer(id uint64) (string, error) {
if swarm.routers[id] != nil {
return swarm.routers[id].Pid, nil
}
newPeerAddr := swarm.notifiee.newPeer
// new node id should be len(swarm.peers)+1
if uint64(len(swarm.routers)+1) == id && swarm.notifiee.newPeer != "" {
swarm.logger.Debugf("Unicast to new peer %s", swarm.notifiee.newPeer)
return newPeerAddr, nil
}
return "", fmt.Errorf("wrong id: %d", id)
}
func (swarm *Swarm) AddNode(newNodeID uint64, vpInfo *pb.VpInfo) {
if _, ok := swarm.routers[newNodeID]; ok {
swarm.logger.Warningf("VP[ID: %d, Pid: %s] has already exist in routing table", newNodeID, vpInfo.Pid)
return
}
swarm.logger.Infof("Add vp[ID: %d, Pid: %s] into routing table", newNodeID, vpInfo.Pid)
// 1. update routers and connectedPeers
swarm.routers[newNodeID] = vpInfo
addInfo, err := constructMultiaddr(vpInfo)
if err != nil {
swarm.logger.Error("Construct AddrInfo failed")
return
}
swarm.connectedPeers.Store(newNodeID, addInfo)
// 2. persist routers
if err := repo.RewriteNetworkConfig(swarm.repo.Config.RepoRoot, swarm.routers, false); err != nil {
swarm.logger.Errorf("Persist routing table failed, err: %s", err.Error())
return
}
return nil
// 3. update notifiee info
swarm.notifiee.setPeers(swarm.routers)
for id, p := range swarm.routers {
swarm.logger.Debugf("=====ID: %d, Addr: %v=====", id, p)
}
if swarm.notifiee.newPeer == vpInfo.Pid {
swarm.logger.Info("Clear notifiee newPeer info")
swarm.notifiee.newPeer = ""
} else if swarm.notifiee.newPeer != "" {
swarm.logger.Warningf("Received vpInfo %v, but it doesn't equal to notifiee newPeer %s", vpInfo, swarm.notifiee.newPeer)
}
}
func (swarm *Swarm) DelNode(delID uint64) {
var (
delNode *pb.VpInfo
ok bool
)
if delNode, ok = swarm.routers[delID]; !ok {
swarm.logger.Warningf("Can't find vp node %d from routing table ", delID)
return
}
swarm.logger.Infof("Delete node [ID: %d, peerInfo: %v] ", delID, delNode)
// 1. update routing table, multiAddrs and connectedPeers
delete(swarm.routers, delID)
delete(swarm.multiAddrs, delID)
swarm.connectedPeers.Delete(delID)
// 2. persist routers
if err := repo.RewriteNetworkConfig(swarm.repo.Config.RepoRoot, swarm.routers, false); err != nil {
swarm.logger.Errorf("Persist routing table failed, err: %s", err.Error())
return
}
for id, p := range swarm.routers {
swarm.logger.Debugf("=====ID: %d, Addr: %v=====", id, p)
}
// 3. update notifiee info
swarm.notifiee.setPeers(swarm.routers)
// 4. deleted node itself will exit the cluster
if delID == swarm.localID {
swarm.reset()
_ = swarm.p2p.Stop()
_ = swarm.Stop()
return
}
}
func (swarm *Swarm) UpdateRouter(vpInfos map[uint64]*pb.VpInfo, isNew bool) bool {
swarm.logger.Infof("Update router: %+v", vpInfos)
// 1. update routing table, multiAddrs and connectedPeers
oldRouters := swarm.routers
swarm.routers = vpInfos
for id, _ := range oldRouters {
if _, ok := vpInfos[id]; !ok {
delete(swarm.multiAddrs, id)
swarm.connectedPeers.Delete(id)
}
}
// 2. persist routers
if err := repo.RewriteNetworkConfig(swarm.repo.Config.RepoRoot, swarm.routers, isNew); err != nil {
swarm.logger.Errorf("Persist routing table failed, err: %s", err.Error())
return false
}
// 3. update notifiee info
swarm.notifiee.setPeers(vpInfos)
// 4. check if a restart node is exist in the routing table, if not, then exit the cluster
var isExist bool
for id, _ := range vpInfos {
if id == swarm.localID {
isExist = true
break
}
}
// deleted node itself will exit the cluster
if !isExist && !isNew {
swarm.reset()
_ = swarm.p2p.Stop()
_ = swarm.Stop()
return true
}
return false
}
func (swarm *Swarm) Disconnect(vpInfos map[uint64]*pb.VpInfo) {
for id, info := range vpInfos {
if err := swarm.p2p.Disconnect(info.Pid); err != nil {
swarm.logger.Errorf("Disconnect peer %s failed, err: %s", err.Error())
}
swarm.logger.Infof("Disconnect peer [ID: %d, Pid: %s]", id, info.Pid)
}
}
func (swarm *Swarm) reset() {
swarm.routers = nil
swarm.multiAddrs = nil
swarm.connectedPeers = sync.Map{}
swarm.notifiee.setPeers(nil)
}
func constructMultiaddr(vpInfo *pb.VpInfo) (*peer.AddrInfo, error) {
addrs := make([]ma.Multiaddr,0)
for _, host := range vpInfo.Hosts {
addr, err := ma.NewMultiaddr(fmt.Sprintf("%s%s", host, vpInfo.Pid))
if err != nil {
return nil, fmt.Errorf("new Multiaddr error:%w", err)
}
addrs = append(addrs, addr)
}
addrInfo := &peer.AddrInfo{
ID: peer.ID(vpInfo.Pid),
Addrs: addrs,
}
return addrInfo, nil
}

View File

@ -1,16 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIClTCCAjygAwIBAgIDAKWTMAoGCCqGSM49BAMCMIGhMQswCQYDVQQGEwJDTjER
MA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MR8wDQYDVQQJEwZz
dHJlZXQwDgYDVQQJEwdhZGRyZXNzMQ8wDQYDVQQREwYzMjQwMDAxEzARBgNVBAoT
Ckh5cGVyY2hhaW4xEDAOBgNVBAsTB0JpdFhIdWIxEzARBgNVBAMTCmJpdHhodWIu
Y24wIBcNMjAwODExMDUwNzEyWhgPMjA3MDA3MzAwNTA3MTJaMIGhMQswCQYDVQQG
EwJDTjERMA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MR8wDQYD
VQQJEwZzdHJlZXQwDgYDVQQJEwdhZGRyZXNzMQ8wDQYDVQQREwYzMjQwMDAxEzAR
BgNVBAoTCkh5cGVyY2hhaW4xEDAOBgNVBAsTB0JpdFhIdWIxEzARBgNVBAMTCmJp
dHhodWIuY24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASznYuB78fMNqgooAnp
YPUfWoQCDAM0nV5YwSj1Rz6RcWKuRAPQooPFb8K2WO6hfRUGtCba+l48FD34R/RP
aajqo18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAPBgNVHRMB
Af8EBTADAQH/MCkGA1UdDgQiBCAWMSMsOINat1TCkhwzFRrFZBJUxLtqAKqjjhBw
4AyVgzAKBggqhkjOPQQDAgNHADBEAiAW5pb+b2aLuEBJCkaEXfukb/HwFsNm7zmx
Ha6oyk0HYAIgXhsMYlIXKf5RmlBFiEWZZRJTyiubI7NDqN5+JlVBAog=
-----END CERTIFICATE-----

View File

@ -1,3 +1,3 @@
-----BEGIN EC PRIVATE KEY-----
halN1RQDWQ1PFJ+SMLb13joI5YiZ3K8Pd3aO+xgl6FQ=
tkdxQ+F/iJJjBE9s9GPcNxd6xFJsTDmno0QZhFcCSi8=
-----END EC PRIVATE KEY-----

View File

@ -1,15 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWTCCAf+gAwIBAgIDCUHDMAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MIICWjCCAf+gAwIBAgIDDhFLMAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MR8wDQYDVQQJEwZz
dHJlZXQwDgYDVQQJEwdhZGRyZXNzMQ8wDQYDVQQREwYzMjQwMDAxDzANBgNVBAoT
BkFnZW5jeTEQMA4GA1UECxMHQml0WEh1YjEQMA4GA1UEAxMHQml0WEh1YjAgFw0y
MDA4MTEwNTA3MTRaGA8yMDcwMDczMDA1MDcxNFowgZkxCzAJBgNVBAYTAkNOMREw
MDA4MTEwNTA3MTNaGA8yMDcwMDczMDA1MDcxM1owgZkxCzAJBgNVBAYTAkNOMREw
DwYDVQQIEwhaaGVKaWFuZzERMA8GA1UEBxMISGFuZ1pob3UxHzANBgNVBAkTBnN0
cmVldDAOBgNVBAkTB2FkZHJlc3MxDzANBgNVBBETBjMyNDAwMDEOMAwGA1UEChMF
Tm9kZTMxEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAAQ9IPBBKkqSwWkwDdK+ARw2qlBmBD9bF8HJ0z3P
XeKaTmnnEBJu1e0vjHl+uQGBz5x1ulBRVeq4xhmkZtPZByO+ozEwLzAOBgNVHQ8B
Tm9kZTExEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAATgjTYEnavxerFuEKJ8C39QUY12xh/TC2E5V7ni
nmQcOgDDRv5HW4sskTSm/WX2D0BMzwb7XE5ATyoDeM9qcurDozEwLzAOBgNVHQ8B
Af8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAMBgNVHRMBAf8EAjAAMAoGCCqGSM49
BAMCA0gAMEUCIQCMgYSwQ9go1jjAcC4SxpJl4moA8Ba/GEb0qwFPaNmSCwIgDEOo
UpUSNYEQJvahR4BxxVLOBf/CNlKhAGBVNKTccxk=
BAMCA0kAMEYCIQD5Oz1xJvFgzYm/lTzoaO/i0ayPVRgSdBwvK6hEICo5lAIhAMtG
aswjd2wVA4zB5GPEmJ/tvPUnxrlOAU67AQMYR4zf
-----END CERTIFICATE-----

View File

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMQcu7NXkY6TE+7xNTSo8CTKG4Tp20CcWAAEVtRQAjlioAoGCCqGSM49
AwEHoUQDQgAEPSDwQSpKksFpMA3SvgEcNqpQZgQ/WxfBydM9z13imk5p5xASbtXt
L4x5frkBgc+cdbpQUVXquMYZpGbT2Qcjvg==
MHcCAQEEIJjph6szT64kRmvzyZYWYaonaFVsvTZwRLqeV20wo2D3oAoGCCqGSM49
AwEHoUQDQgAE4I02BJ2r8XqxbhCifAt/UFGNdsYf0wthOVe54p5kHDoAw0b+R1uL
LJE0pv1l9g9ATM8G+1xOQE8qA3jPanLqww==
-----END EC PRIVATE KEY-----

View File

@ -1,3 +1,3 @@
-----BEGIN EC PRIVATE KEY-----
cu/PS7DoowDT5H5qEPYwvNVA3pM/Ae1TgIl/xeENyV0=
BcNwjTDCxyxLNjFKQfMAc6sY6iJs+Ma59WZyC/4uhjE=
-----END EC PRIVATE KEY-----

View File

@ -1,15 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWTCCAf+gAwIBAgIDCGR3MAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MIICWjCCAf+gAwIBAgIDC8pcMAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MR8wDQYDVQQJEwZz
dHJlZXQwDgYDVQQJEwdhZGRyZXNzMQ8wDQYDVQQREwYzMjQwMDAxDzANBgNVBAoT
BkFnZW5jeTEQMA4GA1UECxMHQml0WEh1YjEQMA4GA1UEAxMHQml0WEh1YjAgFw0y
MDA4MTEwNTA3MTRaGA8yMDcwMDczMDA1MDcxNFowgZkxCzAJBgNVBAYTAkNOMREw
MDA4MTEwNTA3MTNaGA8yMDcwMDczMDA1MDcxM1owgZkxCzAJBgNVBAYTAkNOMREw
DwYDVQQIEwhaaGVKaWFuZzERMA8GA1UEBxMISGFuZ1pob3UxHzANBgNVBAkTBnN0
cmVldDAOBgNVBAkTB2FkZHJlc3MxDzANBgNVBBETBjMyNDAwMDEOMAwGA1UEChMF
Tm9kZTQxEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAARN1y/FhZpSg1kpXF38szDNRXdPkqoc8oRKdGzv
3HdhtBdUO7jXe2xNaWVtNMGXVo+NuBi5t9qEoo+euxfnjlc9ozEwLzAOBgNVHQ8B
Tm9kZTIxEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAARhGDBod719hBcz/lpLtEh8GsqzDhm1ZbjdaTsM
GivsjOHRk9iEkwDtXmsMvYn3yOIq2RR60T7/G2swBzuZiZWxozEwLzAOBgNVHQ8B
Af8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAMBgNVHRMBAf8EAjAAMAoGCCqGSM49
BAMCA0gAMEUCIQCbsG7E158uzqYCzrrnrr2Xsnz7f5cFA2o4SXAF7R/IyAIgSxYS
MGj0g0OBcxJqwTyyvF2FFOhlWjF9nq2eYK/rlzI=
BAMCA0kAMEYCIQDrX3znEJ6zkhUhPN37LY5eurrCs7Brp/TQ/2geHdZLQAIhALxb
Gk39mUrJ/4z/dVGwFYccWZB8UOV1M4iuN6ypF+Sc
-----END CERTIFICATE-----

View File

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFWx/9axMGfzqOO/T3OEBXZNli6dkX/9m+o1GjnEX+I1oAoGCCqGSM49
AwEHoUQDQgAETdcvxYWaUoNZKVxd/LMwzUV3T5KqHPKESnRs79x3YbQXVDu413ts
TWllbTTBl1aPjbgYubfahKKPnrsX545XPQ==
MHcCAQEEICI2QiahAMKtO9tD9VnxZ2J3jvFt+/vTAtcAQzUcIPoXoAoGCCqGSM49
AwEHoUQDQgAEYRgwaHe9fYQXM/5aS7RIfBrKsw4ZtWW43Wk7DBor7Izh0ZPYhJMA
7V5rDL2J98jiKtkUetE+/xtrMAc7mYmVsQ==
-----END EC PRIVATE KEY-----

View File

@ -1,3 +1,3 @@
-----BEGIN EC PRIVATE KEY-----
tkdxQ+F/iJJjBE9s9GPcNxd6xFJsTDmno0QZhFcCSi8=
halN1RQDWQ1PFJ+SMLb13joI5YiZ3K8Pd3aO+xgl6FQ=
-----END EC PRIVATE KEY-----

View File

@ -1,15 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWjCCAf+gAwIBAgIDDhFLMAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MIICWTCCAf+gAwIBAgIDCUHDMAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MR8wDQYDVQQJEwZz
dHJlZXQwDgYDVQQJEwdhZGRyZXNzMQ8wDQYDVQQREwYzMjQwMDAxDzANBgNVBAoT
BkFnZW5jeTEQMA4GA1UECxMHQml0WEh1YjEQMA4GA1UEAxMHQml0WEh1YjAgFw0y
MDA4MTEwNTA3MTNaGA8yMDcwMDczMDA1MDcxM1owgZkxCzAJBgNVBAYTAkNOMREw
MDA4MTEwNTA3MTRaGA8yMDcwMDczMDA1MDcxNFowgZkxCzAJBgNVBAYTAkNOMREw
DwYDVQQIEwhaaGVKaWFuZzERMA8GA1UEBxMISGFuZ1pob3UxHzANBgNVBAkTBnN0
cmVldDAOBgNVBAkTB2FkZHJlc3MxDzANBgNVBBETBjMyNDAwMDEOMAwGA1UEChMF
Tm9kZTExEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAATgjTYEnavxerFuEKJ8C39QUY12xh/TC2E5V7ni
nmQcOgDDRv5HW4sskTSm/WX2D0BMzwb7XE5ATyoDeM9qcurDozEwLzAOBgNVHQ8B
Tm9kZTMxEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAAQ9IPBBKkqSwWkwDdK+ARw2qlBmBD9bF8HJ0z3P
XeKaTmnnEBJu1e0vjHl+uQGBz5x1ulBRVeq4xhmkZtPZByO+ozEwLzAOBgNVHQ8B
Af8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAMBgNVHRMBAf8EAjAAMAoGCCqGSM49
BAMCA0kAMEYCIQD5Oz1xJvFgzYm/lTzoaO/i0ayPVRgSdBwvK6hEICo5lAIhAMtG
aswjd2wVA4zB5GPEmJ/tvPUnxrlOAU67AQMYR4zf
BAMCA0gAMEUCIQCMgYSwQ9go1jjAcC4SxpJl4moA8Ba/GEb0qwFPaNmSCwIgDEOo
UpUSNYEQJvahR4BxxVLOBf/CNlKhAGBVNKTccxk=
-----END CERTIFICATE-----

View File

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJjph6szT64kRmvzyZYWYaonaFVsvTZwRLqeV20wo2D3oAoGCCqGSM49
AwEHoUQDQgAE4I02BJ2r8XqxbhCifAt/UFGNdsYf0wthOVe54p5kHDoAw0b+R1uL
LJE0pv1l9g9ATM8G+1xOQE8qA3jPanLqww==
MHcCAQEEIMQcu7NXkY6TE+7xNTSo8CTKG4Tp20CcWAAEVtRQAjlioAoGCCqGSM49
AwEHoUQDQgAEPSDwQSpKksFpMA3SvgEcNqpQZgQ/WxfBydM9z13imk5p5xASbtXt
L4x5frkBgc+cdbpQUVXquMYZpGbT2Qcjvg==
-----END EC PRIVATE KEY-----

View File

@ -1,3 +1,3 @@
-----BEGIN EC PRIVATE KEY-----
BcNwjTDCxyxLNjFKQfMAc6sY6iJs+Ma59WZyC/4uhjE=
cu/PS7DoowDT5H5qEPYwvNVA3pM/Ae1TgIl/xeENyV0=
-----END EC PRIVATE KEY-----

View File

@ -1,15 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWjCCAf+gAwIBAgIDC8pcMAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MIICWTCCAf+gAwIBAgIDCGR3MAoGCCqGSM49BAMCMIGaMQswCQYDVQQGEwJDTjER
MA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MR8wDQYDVQQJEwZz
dHJlZXQwDgYDVQQJEwdhZGRyZXNzMQ8wDQYDVQQREwYzMjQwMDAxDzANBgNVBAoT
BkFnZW5jeTEQMA4GA1UECxMHQml0WEh1YjEQMA4GA1UEAxMHQml0WEh1YjAgFw0y
MDA4MTEwNTA3MTNaGA8yMDcwMDczMDA1MDcxM1owgZkxCzAJBgNVBAYTAkNOMREw
MDA4MTEwNTA3MTRaGA8yMDcwMDczMDA1MDcxNFowgZkxCzAJBgNVBAYTAkNOMREw
DwYDVQQIEwhaaGVKaWFuZzERMA8GA1UEBxMISGFuZ1pob3UxHzANBgNVBAkTBnN0
cmVldDAOBgNVBAkTB2FkZHJlc3MxDzANBgNVBBETBjMyNDAwMDEOMAwGA1UEChMF
Tm9kZTIxEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAARhGDBod719hBcz/lpLtEh8GsqzDhm1ZbjdaTsM
GivsjOHRk9iEkwDtXmsMvYn3yOIq2RR60T7/G2swBzuZiZWxozEwLzAOBgNVHQ8B
Tm9kZTQxEDAOBgNVBAsTB0JpdFhIdWIxEDAOBgNVBAMTB0JpdFhIdWIwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAARN1y/FhZpSg1kpXF38szDNRXdPkqoc8oRKdGzv
3HdhtBdUO7jXe2xNaWVtNMGXVo+NuBi5t9qEoo+euxfnjlc9ozEwLzAOBgNVHQ8B
Af8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAMBgNVHRMBAf8EAjAAMAoGCCqGSM49
BAMCA0kAMEYCIQDrX3znEJ6zkhUhPN37LY5eurrCs7Brp/TQ/2geHdZLQAIhALxb
Gk39mUrJ/4z/dVGwFYccWZB8UOV1M4iuN6ypF+Sc
BAMCA0gAMEUCIQCbsG7E158uzqYCzrrnrr2Xsnz7f5cFA2o4SXAF7R/IyAIgSxYS
MGj0g0OBcxJqwTyyvF2FFOhlWjF9nq2eYK/rlzI=
-----END CERTIFICATE-----

View File

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICI2QiahAMKtO9tD9VnxZ2J3jvFt+/vTAtcAQzUcIPoXoAoGCCqGSM49
AwEHoUQDQgAEYRgwaHe9fYQXM/5aS7RIfBrKsw4ZtWW43Wk7DBor7Izh0ZPYhJMA
7V5rDL2J98jiKtkUetE+/xtrMAc7mYmVsQ==
MHcCAQEEIFWx/9axMGfzqOO/T3OEBXZNli6dkX/9m+o1GjnEX+I1oAoGCCqGSM49
AwEHoUQDQgAETdcvxYWaUoNZKVxd/LMwzUV3T5KqHPKESnRs79x3YbQXVDu413ts
TWllbTTBl1aPjbgYubfahKKPnrsX545XPQ==
-----END EC PRIVATE KEY-----

View File

@ -72,14 +72,14 @@ func testSendView(suite *API) {
suite.Equal(receipt.Status, pb.Receipt_SUCCESS)
suite.Equal(value, string(receipt.Ret))
}
func (suite *API) TestDelVPNode() {
_, err := suite.api.Network().DelVPNode("")
suite.NotNil(err)
_, err = suite.api.Network().DelVPNode("1234")
suite.Nil(err)
}
//
//func (suite *API) TestDelVPNode() {
// err := suite.api.Broker().DelVPNode(1)
// suite.NotNil(err)
//
// err = suite.api.Broker().DelVPNode(2)
// suite.Nil(err)
//}
func TestAPI(t *testing.T) {
suite.Run(t, &API{})

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvUURnJYTyByepyuLU2wdqsTfNtdty5LFjwhuW2JJquQt+qeV
Oq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KItlhL1zJY/zF3pbVjUsSiPLfSFRvHQ
iltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kgqFmUzxoRUGil2PoJ88vyDit/coSB
IgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU8aMN8dW2kjqW+YwsnxcpVXegDGDp
9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPbKBiseXMzhNspt8r+otE7T0wAfTKN
IVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIkgwIDAQABAoIBAQCI12IXW25r9T1D
0jjGlNmSOQrFpNYOJEzP0CGx0os+kgEoQ3eiWW12J9gWFOrW2SUUcNqqPlLZj1y9
61wQSwk4gvbR9yOjR5bYZyxH9fInIK4nj/fdwJByTPm2g3FlRxeYqUmX+oYpq8ZS
EW7NacMR1MrBPbCc+TxHdugxKxgT42FWcQaUAqTX4SfdHblSh3ae/3xyDgRyB7UC
34JCAWaHZq2d9fVZ6LSCir70VUrq1QvbYNXd2hO5K8c/8+HRy6GanzXn29yff9+j
+I+WkULOmxqQ/N/nhRwuAaRU0Fdgi6wa+8TdXSxIgVsAYdsDcMxwheAL50Cv6kgn
Cn3Wo+JRAoGBAPJv4Hk49SJJdN01OCL/vCc6iLA4dV5HIDp77nMCaaKWOlL4iJFD
eNIfuP5Pi+DvjRouQB52kKXbd61z1eyVJ7gW73iZS92zaO7CNwj7iFmNb8mSjShx
TgdxGxNYoTXb4WPrHbBh3GTrrfBvLEuAYoFIXesHdK60VE33+tadx7J5AoGBAMfb
voEh63kucjoxWHzW/uLoxCaKnGpWCjO6wRjsXZAeNe7tznhuHqgeF9TUVRHnrMa1
pvHVW1w95G9Q1vJymbhuXtGBffjgOgjr6Vf4tIxUUkX+bkUDf+NM+LmkI+g/2h8a
i65b43YuQmnYqyAauOntHWOSuETsXmo/8RFkem/bAoGAfribzMFI4LMksruurByg
bKDb8cCRGMZ0wh0ldlg8fw+nTNc8CzIJZUvPlp5dryWHy7eBLGstEIS2+aMinpcY
O9FBOvhl/2xX3PUHb1qK2sRjOimwPwN6lck5LdOV8GEOXvv2eMuuN9I5CQQTUyO4
WXtKHB+5jdgUeOy14Jh4WYECgYBpPW9NdF0YjLqdpgpggp3pQoS3ftnqrK/mmXrA
8wY5s47W5+aHSAVgpagK7Fx3dzVl1ZW5Vo4rPnQhocHuHSaRFZ1cWQHKodgthnxz
VIVON8CzFs1eDf+z43490w8NZ0ImisXu5HgcbTOPpQZHe4rPs4p8OnBJ6uW0sULx
06UdbQKBgQCMQ3iu/1e83zTnbFa6wecIMZHjitM4G1S+MeT6T/lMGvtf5jQClx2C
JGiqFvwmbfUpxe/8PaSj9nmPUhWk/RrpkjlGry9wedAoLtdzjKOBvOcSjNPNibyD
QGp5IKS37dPJRKl2gxiTSKyb7ba+O2twFm1sgC3zvmfB1qr3T9qPfw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,62 @@
CONNECTED(00000005)
---
Certificate chain
0 s:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
i:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
-----BEGIN CERTIFICATE-----
MIIDhjCCAm4CCQD0t1EOr68uHTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC
Q04xCzAJBgNVBAgMAlpKMQswCQYDVQQHDAJIWjETMBEGA1UECgwKSHlwZXJjaGFp
bjELMAkGA1UECwwCRE0xEjAQBgNVBAMMCWxvY2FsaG9zdDElMCMGCSqGSIb3DQEJ
ARYWZGF0YW1lc2hAaHlwZXJjaGFpbi5jbjAeFw0yMDExMTYwMzAwMDJaFw0yMTEx
MTYwMzAwMDJaMIGEMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNVBAcM
AkhaMRMwEQYDVQQKDApIeXBlcmNoYWluMQswCQYDVQQLDAJETTESMBAGA1UEAwwJ
bG9jYWxob3N0MSUwIwYJKoZIhvcNAQkBFhZkYXRhbWVzaEBoeXBlcmNoYWluLmNu
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvUURnJYTyByepyuLU2wd
qsTfNtdty5LFjwhuW2JJquQt+qeVOq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KIt
lhL1zJY/zF3pbVjUsSiPLfSFRvHQiltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kg
qFmUzxoRUGil2PoJ88vyDit/coSBIgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU
8aMN8dW2kjqW+YwsnxcpVXegDGDp9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPb
KBiseXMzhNspt8r+otE7T0wAfTKNIVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIk
gwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBL0RiqRWBTgeGa0WuncESbg6wy37u3
yWKAbMXGQqiAgDa60cl8H7VOjSgEgFF7ueM4qI7Gg63tqEvYQMfJC7iLnZ0uxlzK
aKwhFVTCBUOdwR1WJrYjO9NpvgR5IzJS4gBI2SixHfKnDAt9kW5ultak+CtN5DLZ
c0xMqay/cZ4Pt3o0yLxYEJrHvhZIeGpYhsBQWngmJKxTVadHSGMbqKX7O+iza4pD
b6r3Uz8HLl2oFmn/T1b5RhuuMS7diQ5y8HzNRYTBdzNmIGovGWg0GQBTZQrUZh6J
75fuj5+DANruj0/MTZqGI71LpqD7QmrKl5Ii+CBknYZPXLnXgw/rGhXE
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
issuer=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 1485 bytes and written 307 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: EF7931988E269C85760BEBBC0379299C1148C3AE8140EA1FD14745C3F0AA4527
Session-ID-ctx:
Master-Key: 08E910F7086C2848818F800ACDBE6D00FE55A896188CDDE281158B1C02D7A458269861E584A3FAECB610BC59C487F322
TLS session ticket:
0000 - 60 f7 27 df 8c 98 71 e3-48 70 29 6f 56 3b 6f 85 `.'...q.Hp)oV;o.
0010 - 16 1f 90 8b 5b 94 c3 c0-94 1c 9d dd e1 83 3f 3c ....[.........?<
0020 - ff cb 93 11 44 ff 57 9d-37 97 8d 8e 04 e2 19 bc ....D.W.7.......
0030 - 6f 75 df b5 fd 00 bb ee-ba 56 c6 fd b2 21 8d ae ou.......V...!..
0040 - f5 39 94 82 69 fa 7f 97-c5 3f 4f 50 20 0f dc d8 .9..i....?OP ...
0050 - 60 00 a0 37 f8 59 19 4d-5c 87 08 e6 37 82 b9 34 `..7.Y.M\...7..4
0060 - 3c 56 38 f1 db cf 4f e1-99 7a dd 50 b0 a8 7a 83 <V8...O..z.P..z.
0070 - 26 82 80 8d 2e ec 0b 67- &......g
Start Time: 1605496292
Timeout : 7200 (sec)
Verify return code: 18 (self signed certificate)
---

View File

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

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvUURnJYTyByepyuLU2wdqsTfNtdty5LFjwhuW2JJquQt+qeV
Oq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KItlhL1zJY/zF3pbVjUsSiPLfSFRvHQ
iltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kgqFmUzxoRUGil2PoJ88vyDit/coSB
IgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU8aMN8dW2kjqW+YwsnxcpVXegDGDp
9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPbKBiseXMzhNspt8r+otE7T0wAfTKN
IVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIkgwIDAQABAoIBAQCI12IXW25r9T1D
0jjGlNmSOQrFpNYOJEzP0CGx0os+kgEoQ3eiWW12J9gWFOrW2SUUcNqqPlLZj1y9
61wQSwk4gvbR9yOjR5bYZyxH9fInIK4nj/fdwJByTPm2g3FlRxeYqUmX+oYpq8ZS
EW7NacMR1MrBPbCc+TxHdugxKxgT42FWcQaUAqTX4SfdHblSh3ae/3xyDgRyB7UC
34JCAWaHZq2d9fVZ6LSCir70VUrq1QvbYNXd2hO5K8c/8+HRy6GanzXn29yff9+j
+I+WkULOmxqQ/N/nhRwuAaRU0Fdgi6wa+8TdXSxIgVsAYdsDcMxwheAL50Cv6kgn
Cn3Wo+JRAoGBAPJv4Hk49SJJdN01OCL/vCc6iLA4dV5HIDp77nMCaaKWOlL4iJFD
eNIfuP5Pi+DvjRouQB52kKXbd61z1eyVJ7gW73iZS92zaO7CNwj7iFmNb8mSjShx
TgdxGxNYoTXb4WPrHbBh3GTrrfBvLEuAYoFIXesHdK60VE33+tadx7J5AoGBAMfb
voEh63kucjoxWHzW/uLoxCaKnGpWCjO6wRjsXZAeNe7tznhuHqgeF9TUVRHnrMa1
pvHVW1w95G9Q1vJymbhuXtGBffjgOgjr6Vf4tIxUUkX+bkUDf+NM+LmkI+g/2h8a
i65b43YuQmnYqyAauOntHWOSuETsXmo/8RFkem/bAoGAfribzMFI4LMksruurByg
bKDb8cCRGMZ0wh0ldlg8fw+nTNc8CzIJZUvPlp5dryWHy7eBLGstEIS2+aMinpcY
O9FBOvhl/2xX3PUHb1qK2sRjOimwPwN6lck5LdOV8GEOXvv2eMuuN9I5CQQTUyO4
WXtKHB+5jdgUeOy14Jh4WYECgYBpPW9NdF0YjLqdpgpggp3pQoS3ftnqrK/mmXrA
8wY5s47W5+aHSAVgpagK7Fx3dzVl1ZW5Vo4rPnQhocHuHSaRFZ1cWQHKodgthnxz
VIVON8CzFs1eDf+z43490w8NZ0ImisXu5HgcbTOPpQZHe4rPs4p8OnBJ6uW0sULx
06UdbQKBgQCMQ3iu/1e83zTnbFa6wecIMZHjitM4G1S+MeT6T/lMGvtf5jQClx2C
JGiqFvwmbfUpxe/8PaSj9nmPUhWk/RrpkjlGry9wedAoLtdzjKOBvOcSjNPNibyD
QGp5IKS37dPJRKl2gxiTSKyb7ba+O2twFm1sgC3zvmfB1qr3T9qPfw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,62 @@
CONNECTED(00000005)
---
Certificate chain
0 s:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
i:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
-----BEGIN CERTIFICATE-----
MIIDhjCCAm4CCQD0t1EOr68uHTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC
Q04xCzAJBgNVBAgMAlpKMQswCQYDVQQHDAJIWjETMBEGA1UECgwKSHlwZXJjaGFp
bjELMAkGA1UECwwCRE0xEjAQBgNVBAMMCWxvY2FsaG9zdDElMCMGCSqGSIb3DQEJ
ARYWZGF0YW1lc2hAaHlwZXJjaGFpbi5jbjAeFw0yMDExMTYwMzAwMDJaFw0yMTEx
MTYwMzAwMDJaMIGEMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNVBAcM
AkhaMRMwEQYDVQQKDApIeXBlcmNoYWluMQswCQYDVQQLDAJETTESMBAGA1UEAwwJ
bG9jYWxob3N0MSUwIwYJKoZIhvcNAQkBFhZkYXRhbWVzaEBoeXBlcmNoYWluLmNu
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvUURnJYTyByepyuLU2wd
qsTfNtdty5LFjwhuW2JJquQt+qeVOq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KIt
lhL1zJY/zF3pbVjUsSiPLfSFRvHQiltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kg
qFmUzxoRUGil2PoJ88vyDit/coSBIgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU
8aMN8dW2kjqW+YwsnxcpVXegDGDp9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPb
KBiseXMzhNspt8r+otE7T0wAfTKNIVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIk
gwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBL0RiqRWBTgeGa0WuncESbg6wy37u3
yWKAbMXGQqiAgDa60cl8H7VOjSgEgFF7ueM4qI7Gg63tqEvYQMfJC7iLnZ0uxlzK
aKwhFVTCBUOdwR1WJrYjO9NpvgR5IzJS4gBI2SixHfKnDAt9kW5ultak+CtN5DLZ
c0xMqay/cZ4Pt3o0yLxYEJrHvhZIeGpYhsBQWngmJKxTVadHSGMbqKX7O+iza4pD
b6r3Uz8HLl2oFmn/T1b5RhuuMS7diQ5y8HzNRYTBdzNmIGovGWg0GQBTZQrUZh6J
75fuj5+DANruj0/MTZqGI71LpqD7QmrKl5Ii+CBknYZPXLnXgw/rGhXE
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
issuer=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 1485 bytes and written 307 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: EF7931988E269C85760BEBBC0379299C1148C3AE8140EA1FD14745C3F0AA4527
Session-ID-ctx:
Master-Key: 08E910F7086C2848818F800ACDBE6D00FE55A896188CDDE281158B1C02D7A458269861E584A3FAECB610BC59C487F322
TLS session ticket:
0000 - 60 f7 27 df 8c 98 71 e3-48 70 29 6f 56 3b 6f 85 `.'...q.Hp)oV;o.
0010 - 16 1f 90 8b 5b 94 c3 c0-94 1c 9d dd e1 83 3f 3c ....[.........?<
0020 - ff cb 93 11 44 ff 57 9d-37 97 8d 8e 04 e2 19 bc ....D.W.7.......
0030 - 6f 75 df b5 fd 00 bb ee-ba 56 c6 fd b2 21 8d ae ou.......V...!..
0040 - f5 39 94 82 69 fa 7f 97-c5 3f 4f 50 20 0f dc d8 .9..i....?OP ...
0050 - 60 00 a0 37 f8 59 19 4d-5c 87 08 e6 37 82 b9 34 `..7.Y.M\...7..4
0060 - 3c 56 38 f1 db cf 4f e1-99 7a dd 50 b0 a8 7a 83 <V8...O..z.P..z.
0070 - 26 82 80 8d 2e ec 0b 67- &......g
Start Time: 1605496292
Timeout : 7200 (sec)
Verify return code: 18 (self signed certificate)
---

View File

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

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvUURnJYTyByepyuLU2wdqsTfNtdty5LFjwhuW2JJquQt+qeV
Oq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KItlhL1zJY/zF3pbVjUsSiPLfSFRvHQ
iltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kgqFmUzxoRUGil2PoJ88vyDit/coSB
IgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU8aMN8dW2kjqW+YwsnxcpVXegDGDp
9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPbKBiseXMzhNspt8r+otE7T0wAfTKN
IVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIkgwIDAQABAoIBAQCI12IXW25r9T1D
0jjGlNmSOQrFpNYOJEzP0CGx0os+kgEoQ3eiWW12J9gWFOrW2SUUcNqqPlLZj1y9
61wQSwk4gvbR9yOjR5bYZyxH9fInIK4nj/fdwJByTPm2g3FlRxeYqUmX+oYpq8ZS
EW7NacMR1MrBPbCc+TxHdugxKxgT42FWcQaUAqTX4SfdHblSh3ae/3xyDgRyB7UC
34JCAWaHZq2d9fVZ6LSCir70VUrq1QvbYNXd2hO5K8c/8+HRy6GanzXn29yff9+j
+I+WkULOmxqQ/N/nhRwuAaRU0Fdgi6wa+8TdXSxIgVsAYdsDcMxwheAL50Cv6kgn
Cn3Wo+JRAoGBAPJv4Hk49SJJdN01OCL/vCc6iLA4dV5HIDp77nMCaaKWOlL4iJFD
eNIfuP5Pi+DvjRouQB52kKXbd61z1eyVJ7gW73iZS92zaO7CNwj7iFmNb8mSjShx
TgdxGxNYoTXb4WPrHbBh3GTrrfBvLEuAYoFIXesHdK60VE33+tadx7J5AoGBAMfb
voEh63kucjoxWHzW/uLoxCaKnGpWCjO6wRjsXZAeNe7tznhuHqgeF9TUVRHnrMa1
pvHVW1w95G9Q1vJymbhuXtGBffjgOgjr6Vf4tIxUUkX+bkUDf+NM+LmkI+g/2h8a
i65b43YuQmnYqyAauOntHWOSuETsXmo/8RFkem/bAoGAfribzMFI4LMksruurByg
bKDb8cCRGMZ0wh0ldlg8fw+nTNc8CzIJZUvPlp5dryWHy7eBLGstEIS2+aMinpcY
O9FBOvhl/2xX3PUHb1qK2sRjOimwPwN6lck5LdOV8GEOXvv2eMuuN9I5CQQTUyO4
WXtKHB+5jdgUeOy14Jh4WYECgYBpPW9NdF0YjLqdpgpggp3pQoS3ftnqrK/mmXrA
8wY5s47W5+aHSAVgpagK7Fx3dzVl1ZW5Vo4rPnQhocHuHSaRFZ1cWQHKodgthnxz
VIVON8CzFs1eDf+z43490w8NZ0ImisXu5HgcbTOPpQZHe4rPs4p8OnBJ6uW0sULx
06UdbQKBgQCMQ3iu/1e83zTnbFa6wecIMZHjitM4G1S+MeT6T/lMGvtf5jQClx2C
JGiqFvwmbfUpxe/8PaSj9nmPUhWk/RrpkjlGry9wedAoLtdzjKOBvOcSjNPNibyD
QGp5IKS37dPJRKl2gxiTSKyb7ba+O2twFm1sgC3zvmfB1qr3T9qPfw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,62 @@
CONNECTED(00000005)
---
Certificate chain
0 s:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
i:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
-----BEGIN CERTIFICATE-----
MIIDhjCCAm4CCQD0t1EOr68uHTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC
Q04xCzAJBgNVBAgMAlpKMQswCQYDVQQHDAJIWjETMBEGA1UECgwKSHlwZXJjaGFp
bjELMAkGA1UECwwCRE0xEjAQBgNVBAMMCWxvY2FsaG9zdDElMCMGCSqGSIb3DQEJ
ARYWZGF0YW1lc2hAaHlwZXJjaGFpbi5jbjAeFw0yMDExMTYwMzAwMDJaFw0yMTEx
MTYwMzAwMDJaMIGEMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNVBAcM
AkhaMRMwEQYDVQQKDApIeXBlcmNoYWluMQswCQYDVQQLDAJETTESMBAGA1UEAwwJ
bG9jYWxob3N0MSUwIwYJKoZIhvcNAQkBFhZkYXRhbWVzaEBoeXBlcmNoYWluLmNu
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvUURnJYTyByepyuLU2wd
qsTfNtdty5LFjwhuW2JJquQt+qeVOq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KIt
lhL1zJY/zF3pbVjUsSiPLfSFRvHQiltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kg
qFmUzxoRUGil2PoJ88vyDit/coSBIgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU
8aMN8dW2kjqW+YwsnxcpVXegDGDp9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPb
KBiseXMzhNspt8r+otE7T0wAfTKNIVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIk
gwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBL0RiqRWBTgeGa0WuncESbg6wy37u3
yWKAbMXGQqiAgDa60cl8H7VOjSgEgFF7ueM4qI7Gg63tqEvYQMfJC7iLnZ0uxlzK
aKwhFVTCBUOdwR1WJrYjO9NpvgR5IzJS4gBI2SixHfKnDAt9kW5ultak+CtN5DLZ
c0xMqay/cZ4Pt3o0yLxYEJrHvhZIeGpYhsBQWngmJKxTVadHSGMbqKX7O+iza4pD
b6r3Uz8HLl2oFmn/T1b5RhuuMS7diQ5y8HzNRYTBdzNmIGovGWg0GQBTZQrUZh6J
75fuj5+DANruj0/MTZqGI71LpqD7QmrKl5Ii+CBknYZPXLnXgw/rGhXE
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
issuer=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 1485 bytes and written 307 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: EF7931988E269C85760BEBBC0379299C1148C3AE8140EA1FD14745C3F0AA4527
Session-ID-ctx:
Master-Key: 08E910F7086C2848818F800ACDBE6D00FE55A896188CDDE281158B1C02D7A458269861E584A3FAECB610BC59C487F322
TLS session ticket:
0000 - 60 f7 27 df 8c 98 71 e3-48 70 29 6f 56 3b 6f 85 `.'...q.Hp)oV;o.
0010 - 16 1f 90 8b 5b 94 c3 c0-94 1c 9d dd e1 83 3f 3c ....[.........?<
0020 - ff cb 93 11 44 ff 57 9d-37 97 8d 8e 04 e2 19 bc ....D.W.7.......
0030 - 6f 75 df b5 fd 00 bb ee-ba 56 c6 fd b2 21 8d ae ou.......V...!..
0040 - f5 39 94 82 69 fa 7f 97-c5 3f 4f 50 20 0f dc d8 .9..i....?OP ...
0050 - 60 00 a0 37 f8 59 19 4d-5c 87 08 e6 37 82 b9 34 `..7.Y.M\...7..4
0060 - 3c 56 38 f1 db cf 4f e1-99 7a dd 50 b0 a8 7a 83 <V8...O..z.P..z.
0070 - 26 82 80 8d 2e ec 0b 67- &......g
Start Time: 1605496292
Timeout : 7200 (sec)
Verify return code: 18 (self signed certificate)
---

View File

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

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvUURnJYTyByepyuLU2wdqsTfNtdty5LFjwhuW2JJquQt+qeV
Oq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KItlhL1zJY/zF3pbVjUsSiPLfSFRvHQ
iltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kgqFmUzxoRUGil2PoJ88vyDit/coSB
IgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU8aMN8dW2kjqW+YwsnxcpVXegDGDp
9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPbKBiseXMzhNspt8r+otE7T0wAfTKN
IVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIkgwIDAQABAoIBAQCI12IXW25r9T1D
0jjGlNmSOQrFpNYOJEzP0CGx0os+kgEoQ3eiWW12J9gWFOrW2SUUcNqqPlLZj1y9
61wQSwk4gvbR9yOjR5bYZyxH9fInIK4nj/fdwJByTPm2g3FlRxeYqUmX+oYpq8ZS
EW7NacMR1MrBPbCc+TxHdugxKxgT42FWcQaUAqTX4SfdHblSh3ae/3xyDgRyB7UC
34JCAWaHZq2d9fVZ6LSCir70VUrq1QvbYNXd2hO5K8c/8+HRy6GanzXn29yff9+j
+I+WkULOmxqQ/N/nhRwuAaRU0Fdgi6wa+8TdXSxIgVsAYdsDcMxwheAL50Cv6kgn
Cn3Wo+JRAoGBAPJv4Hk49SJJdN01OCL/vCc6iLA4dV5HIDp77nMCaaKWOlL4iJFD
eNIfuP5Pi+DvjRouQB52kKXbd61z1eyVJ7gW73iZS92zaO7CNwj7iFmNb8mSjShx
TgdxGxNYoTXb4WPrHbBh3GTrrfBvLEuAYoFIXesHdK60VE33+tadx7J5AoGBAMfb
voEh63kucjoxWHzW/uLoxCaKnGpWCjO6wRjsXZAeNe7tznhuHqgeF9TUVRHnrMa1
pvHVW1w95G9Q1vJymbhuXtGBffjgOgjr6Vf4tIxUUkX+bkUDf+NM+LmkI+g/2h8a
i65b43YuQmnYqyAauOntHWOSuETsXmo/8RFkem/bAoGAfribzMFI4LMksruurByg
bKDb8cCRGMZ0wh0ldlg8fw+nTNc8CzIJZUvPlp5dryWHy7eBLGstEIS2+aMinpcY
O9FBOvhl/2xX3PUHb1qK2sRjOimwPwN6lck5LdOV8GEOXvv2eMuuN9I5CQQTUyO4
WXtKHB+5jdgUeOy14Jh4WYECgYBpPW9NdF0YjLqdpgpggp3pQoS3ftnqrK/mmXrA
8wY5s47W5+aHSAVgpagK7Fx3dzVl1ZW5Vo4rPnQhocHuHSaRFZ1cWQHKodgthnxz
VIVON8CzFs1eDf+z43490w8NZ0ImisXu5HgcbTOPpQZHe4rPs4p8OnBJ6uW0sULx
06UdbQKBgQCMQ3iu/1e83zTnbFa6wecIMZHjitM4G1S+MeT6T/lMGvtf5jQClx2C
JGiqFvwmbfUpxe/8PaSj9nmPUhWk/RrpkjlGry9wedAoLtdzjKOBvOcSjNPNibyD
QGp5IKS37dPJRKl2gxiTSKyb7ba+O2twFm1sgC3zvmfB1qr3T9qPfw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,62 @@
CONNECTED(00000005)
---
Certificate chain
0 s:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
i:/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
-----BEGIN CERTIFICATE-----
MIIDhjCCAm4CCQD0t1EOr68uHTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC
Q04xCzAJBgNVBAgMAlpKMQswCQYDVQQHDAJIWjETMBEGA1UECgwKSHlwZXJjaGFp
bjELMAkGA1UECwwCRE0xEjAQBgNVBAMMCWxvY2FsaG9zdDElMCMGCSqGSIb3DQEJ
ARYWZGF0YW1lc2hAaHlwZXJjaGFpbi5jbjAeFw0yMDExMTYwMzAwMDJaFw0yMTEx
MTYwMzAwMDJaMIGEMQswCQYDVQQGEwJDTjELMAkGA1UECAwCWkoxCzAJBgNVBAcM
AkhaMRMwEQYDVQQKDApIeXBlcmNoYWluMQswCQYDVQQLDAJETTESMBAGA1UEAwwJ
bG9jYWxob3N0MSUwIwYJKoZIhvcNAQkBFhZkYXRhbWVzaEBoeXBlcmNoYWluLmNu
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvUURnJYTyByepyuLU2wd
qsTfNtdty5LFjwhuW2JJquQt+qeVOq9y65nKnr/8x1dIE4Z5zmWh2bpTzddT6KIt
lhL1zJY/zF3pbVjUsSiPLfSFRvHQiltUZspKgGij/Tb9I/4hy7vvv95ff6v7C3kg
qFmUzxoRUGil2PoJ88vyDit/coSBIgqTR9QonutL1RIgurraTcGHLPpRqFuPouvU
8aMN8dW2kjqW+YwsnxcpVXegDGDp9k8i2iDcwpMF6C8n7il47O8LWmAMpcT7nsPb
KBiseXMzhNspt8r+otE7T0wAfTKNIVVuEkq/1HQZBUPtnhpTJREHI1kX3Znt4eIk
gwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBL0RiqRWBTgeGa0WuncESbg6wy37u3
yWKAbMXGQqiAgDa60cl8H7VOjSgEgFF7ueM4qI7Gg63tqEvYQMfJC7iLnZ0uxlzK
aKwhFVTCBUOdwR1WJrYjO9NpvgR5IzJS4gBI2SixHfKnDAt9kW5ultak+CtN5DLZ
c0xMqay/cZ4Pt3o0yLxYEJrHvhZIeGpYhsBQWngmJKxTVadHSGMbqKX7O+iza4pD
b6r3Uz8HLl2oFmn/T1b5RhuuMS7diQ5y8HzNRYTBdzNmIGovGWg0GQBTZQrUZh6J
75fuj5+DANruj0/MTZqGI71LpqD7QmrKl5Ii+CBknYZPXLnXgw/rGhXE
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
issuer=/C=CN/ST=ZJ/L=HZ/O=Hyperchain/OU=DM/CN=localhost/emailAddress=datamesh@hyperchain.cn
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 1485 bytes and written 307 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: EF7931988E269C85760BEBBC0379299C1148C3AE8140EA1FD14745C3F0AA4527
Session-ID-ctx:
Master-Key: 08E910F7086C2848818F800ACDBE6D00FE55A896188CDDE281158B1C02D7A458269861E584A3FAECB610BC59C487F322
TLS session ticket:
0000 - 60 f7 27 df 8c 98 71 e3-48 70 29 6f 56 3b 6f 85 `.'...q.Hp)oV;o.
0010 - 16 1f 90 8b 5b 94 c3 c0-94 1c 9d dd e1 83 3f 3c ....[.........?<
0020 - ff cb 93 11 44 ff 57 9d-37 97 8d 8e 04 e2 19 bc ....D.W.7.......
0030 - 6f 75 df b5 fd 00 bb ee-ba 56 c6 fd b2 21 8d ae ou.......V...!..
0040 - f5 39 94 82 69 fa 7f 97-c5 3f 4f 50 20 0f dc d8 .9..i....?OP ...
0050 - 60 00 a0 37 f8 59 19 4d-5c 87 08 e6 37 82 b9 34 `..7.Y.M\...7..4
0060 - 3c 56 38 f1 db cf 4f e1-99 7a dd 50 b0 a8 7a 83 <V8...O..z.P..z.
0070 - 26 82 80 8d 2e ec 0b 67- &......g
Start Time: 1605496292
Timeout : 7200 (sec)
Verify return code: 18 (self signed certificate)
---

View File

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

View File

@ -1,17 +1,21 @@
package tester
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/meshplus/bitxhub/internal/app"
"github.com/meshplus/bitxhub/internal/coreapi"
"github.com/meshplus/bitxhub/internal/coreapi/api"
"github.com/meshplus/bitxhub/internal/loggers"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/internal/router"
"github.com/meshplus/bitxhub/pkg/order"
"github.com/meshplus/bitxhub/pkg/order/etcdraft"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
func TestTester(t *testing.T) {
@ -32,7 +36,7 @@ func TestTester(t *testing.T) {
time.Sleep(500 * time.Millisecond)
}
suite.Run(t, &API{api: node1})
//suite.Run(t, &API{api: node1})
suite.Run(t, &RegisterAppchain{api: node2})
suite.Run(t, &Interchain{api: node3})
suite.Run(t, &Role{api: node4})
@ -48,7 +52,7 @@ func setupNode(t *testing.T, path string) api.CoreAPI {
loggers.Initialize(repo.Config)
bxh, err := app.NewTesterBitXHub(repo)
bxh, err := newTesterBitXHub(repo)
require.Nil(t, err)
api, err := coreapi.New(bxh)
@ -61,3 +65,49 @@ func setupNode(t *testing.T, path string) api.CoreAPI {
return api
}
func newTesterBitXHub(rep *repo.Repo) (*app.BitXHub, error) {
repoRoot := rep.Config.RepoRoot
bxh, err := app.GenerateBitXHubWithoutOrder(rep)
if err != nil {
return nil, err
}
chainMeta := bxh.Ledger.GetChainMeta()
m := rep.NetworkConfig.GetVpInfos()
order, err := etcdraft.NewNode(
order.WithRepoRoot(repoRoot),
order.WithStoragePath(repo.GetStoragePath(repoRoot, "order")),
order.WithPluginPath(rep.Config.Plugin),
order.WithNodes(m),
order.WithID(rep.NetworkConfig.ID),
order.WithIsNew(rep.NetworkConfig.IsNew),
order.WithPeerManager(bxh.PeerMgr),
order.WithLogger(loggers.Logger(loggers.Order)),
order.WithApplied(chainMeta.Height),
order.WithDigest(chainMeta.BlockHash.String()),
order.WithGetChainMetaFunc(bxh.Ledger.GetChainMeta),
order.WithGetTransactionFunc(bxh.Ledger.GetTransaction),
order.WithGetBlockByHeightFunc(bxh.Ledger.GetBlock),
)
if err != nil {
return nil, err
}
r, err := router.New(loggers.Logger(loggers.Router), rep, bxh.Ledger, bxh.PeerMgr, order.Quorum())
if err != nil {
return nil, fmt.Errorf("create InterchainRouter: %w", err)
}
ctx, cancel := context.WithCancel(context.Background())
bxh.Ctx = ctx
bxh.Cancel = cancel
bxh.Order = order
bxh.Router = r
return bxh, nil
}