feat(*): add delete vp node feature

This commit is contained in:
Lizen0512 2020-12-08 16:42:56 +08:00
parent 7ab92d6f2b
commit 131b086563
27 changed files with 266 additions and 107 deletions

View File

@ -2,8 +2,6 @@ package grpc
import (
"context"
"encoding/json"
"github.com/meshplus/bitxhub-model/pb"
)
@ -17,13 +15,3 @@ func GetChainStatus(cbs *ChainBrokerService) (*pb.Response, error) {
}, nil
}
func GetValidators(cbs *ChainBrokerService) (*pb.Response, error) {
addresses := cbs.genesis.Addresses
v, err := json.Marshal(addresses)
if err != nil {
return nil, err
}
return &pb.Response{
Data: v,
}, nil
}

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
}

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

@ -0,0 +1,62 @@
package grpc
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/pkg/peermgr"
)
func GetValidators(cbs *ChainBrokerService) (*pb.Response, error) {
addresses := cbs.genesis.Addresses
v, err := json.Marshal(addresses)
if err != nil {
return nil, err
}
return &pb.Response{
Data: v,
}, nil
}
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]*peermgr.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.IPAddr == 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,30 @@ 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
}
data, err := httpGet(url)
if err != nil {
return err
}
fmt.Println(string(data))
return nil
}

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

@ -58,6 +58,7 @@ type Node struct {
justElected bool
isRestart bool
// TODO (YH): refactor
ctx context.Context // context
haltC chan struct{} // exit signal
@ -655,6 +656,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

@ -130,7 +130,11 @@ func (mpm *mockPeerMgr)AddNode(newNodeID uint64, vpInfo *peermgr.VPInfo) {}
func (mpm *mockPeerMgr)DelNode(delID uint64){}
func (mpm *mockPeerMgr)UpdateRouter(vpInfos map[uint64]*peermgr.VPInfo) {}
func (mpm *mockPeerMgr)UpdateRouter(vpInfos map[uint64]*peermgr.VPInfo, isNew bool) bool {
return false
}
func (mpm *mockPeerMgr)Disconnect(vpInfos map[uint64]*peermgr.VPInfo) {}
func (mpm *mockPeerMgr) Peers() map[uint64]*peermgr.VPInfo {
peers := make(map[uint64]*peermgr.VPInfo, 3)

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

@ -57,6 +57,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

View File

@ -9,8 +9,9 @@ import (
type notifiee struct {
peers map[uint64]*VPInfo
// TODO (Peer): keep access goroutine safety
newPeer string
mu sync.Mutex
mu sync.RWMutex
logger logrus.FieldLogger
}
@ -28,11 +29,10 @@ func (n *notifiee) ListenClose(network network.Network, multiaddr ma.Multiaddr)
}
func (n *notifiee) Connected(network network.Network, conn network.Conn) {
n.mu.Lock()
defer n.mu.Unlock()
peers := n.getPeers()
newAddr := conn.RemotePeer().String()
// check if the newAddr has already in peers.
for _, p := range n.peers {
for _, p := range peers {
if p.IPAddr == newAddr {
return
}
@ -52,3 +52,15 @@ 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]*VPInfo {
n.mu.RLock()
defer n.mu.RUnlock()
return n.peers
}
func (n *notifiee) setPeers(peers map[uint64]*VPInfo) {
n.mu.Lock()
defer n.mu.Unlock()
n.peers = peers
}

View File

@ -37,9 +37,15 @@ type PeerManager interface {
// SubscribeOrderMessage
SubscribeOrderMessage(ch chan<- events.OrderMessageEvent) event.Subscription
// AddNode adds a vp peer.
AddNode(newNodeID uint64, vpInfo *VPInfo)
// DelNode deletes a vp peer.
DelNode(delID uint64)
UpdateRouter (vpInfos map[uint64]*VPInfo)
// UpdateRouter update the local router to quorum router.
UpdateRouter (vpInfos map[uint64]*VPInfo, isNew bool) bool
// Disconnect disconnect with all vp peers.
Disconnect(vpInfos map[uint64]*VPInfo)
}

View File

@ -3,7 +3,6 @@ package peermgr
import (
"context"
"fmt"
"github.com/meshplus/bitxhub-kit/types"
"sync"
"time"
@ -12,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/protocol"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/internal/model"
@ -72,8 +72,8 @@ func New(repoConfig *repo.Repo, logger logrus.FieldLogger, ledger ledger.Ledger)
}
IpInfo := repo.NetworkConfig.VpNodes[node.ID]
addInfo := &peer.AddrInfo{
ID:IpInfo.ID,
Addrs:IpInfo.Addrs,
ID: IpInfo.ID,
Addrs: IpInfo.Addrs,
}
multiAddrs[node.ID] = addInfo
}
@ -104,9 +104,9 @@ func New(repoConfig *repo.Repo, logger logrus.FieldLogger, ledger ledger.Ledger)
p2p: p2p,
logger: logger,
ledger: ledger,
enablePing: repoConfig.Config.Ping.Enable,
pingTimeout: repoConfig.Config.Ping.Duration,
routers: peers,
enablePing: repo.Config.Ping.Enable,
pingTimeout: repo.Config.Ping.Duration,
routers: validators,
multiAddrs: multiAddrs,
connectedPeers: sync.Map{},
notifiee: notifiee,
@ -202,6 +202,8 @@ func (swarm *Swarm) Ping() {
return true
})
swarm.logger.WithFields(fields).Info("ping time")
case <-swarm.ctx.Done():
return
}
}
}
@ -269,7 +271,6 @@ func (swarm *Swarm) Broadcast(msg *pb.Message) error {
// if we are in adding node but hasn't finished updateN, new node hash will be temporarily recorded
// in swarm.notifiee.newPeer.
// TODO (Peer): keep access goroutine safety
if swarm.notifiee.newPeer != "" {
swarm.logger.Debugf("Broadcast to new peer %s", swarm.notifiee.newPeer)
addrs = append(addrs, swarm.notifiee.newPeer)
@ -284,12 +285,12 @@ func (swarm *Swarm) Broadcast(msg *pb.Message) error {
}
func (swarm *Swarm) Peers() map[uint64]*VPInfo {
return swarm.routers
return swarm.notifiee.getPeers()
}
func (swarm *Swarm) OtherPeers() map[uint64]*peer.AddrInfo {
addrInfos := make(map[uint64]*peer.AddrInfo)
for id, addr := range swarm.Peers() {
for id, addr := range swarm.notifiee.getPeers() {
if id == swarm.localID {
continue
}
@ -350,16 +351,15 @@ func (swarm *Swarm) findPeer(id uint64) (string, error) {
if swarm.routers[id] != nil {
return swarm.routers[id].IPAddr, nil
}
swarm.notifiee.mu.Lock()
newPeerAddr := swarm.notifiee.newPeer
swarm.notifiee.mu.Unlock()
// new node id should be len(swarm.peers)+1,
if uint64(len(swarm.routers)+1) == id && newPeerAddr != "" {
// new node id should be len(swarm.peers)+1
if uint64(len(swarm.routers)+1) == id && swarm.notifiee.newPeer != "" {
return newPeerAddr, nil
}
return "", fmt.Errorf("wrong id: %d", id)
}
// todo (YH): persist config and update connectedPeers and multiAddrs info?
func (swarm *Swarm) AddNode(newNodeID uint64, vpInfo *VPInfo) {
if _, ok := swarm.routers[newNodeID]; ok {
swarm.logger.Warningf("VP[ID: %d, IpAddr: %s] has already exist in routing table", newNodeID, vpInfo.IPAddr)
@ -367,31 +367,82 @@ func (swarm *Swarm) AddNode(newNodeID uint64, vpInfo *VPInfo) {
}
swarm.logger.Infof("Add vp[ID: %d, IpAddr: %s] into routing table", newNodeID, vpInfo.IPAddr)
swarm.routers[newNodeID] = vpInfo
for index, p := range swarm.routers {
swarm.logger.Debugf("=====ID: %d, Addr: %v=====", index+1, p)
for id, p := range swarm.routers {
swarm.logger.Debugf("=====ID: %d, Addr: %v=====", id, p)
}
// update notifiee info
swarm.notifiee.mu.Lock()
swarm.notifiee.peers[newNodeID] = vpInfo
swarm.notifiee.setPeers(swarm.routers)
if swarm.notifiee.newPeer == vpInfo.IPAddr {
swarm.logger.Info("Clear notifiee newPeer info")
swarm.notifiee.newPeer = ""
} else {
swarm.logger.Warningf("Received vpInfo %v, but it doesn't equal to notifiee newPeer %s", vpInfo, swarm.notifiee.newPeer)
}
swarm.notifiee.mu.Unlock()
}
func (swarm *Swarm) DelNode(delID uint64) {
if delID == swarm.localID {
// deleted node itself will exit the cluster
swarm.reset()
_ = swarm.p2p.Stop()
_ = swarm.Stop()
return
}
var (
delNode *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)
delete(swarm.routers, delID)
delete(swarm.multiAddrs, delID)
swarm.connectedPeers.Delete(delID)
for id, p := range swarm.routers {
swarm.logger.Debugf("=====ID: %d, Addr: %v=====", id, p)
}
// update notifiee info
swarm.notifiee.setPeers(swarm.routers)
}
func (swarm *Swarm) UpdateRouter(vpInfos map[uint64]*VPInfo) {
func (swarm *Swarm) UpdateRouter(vpInfos map[uint64]*VPInfo, isNew bool) bool {
swarm.logger.Infof("Update router: %+v", vpInfos)
swarm.routers = vpInfos
// check if self is exist in the routing table, and if not, exit the cluster
var isExist bool
for id, _ := range vpInfos {
if id == swarm.localID {
isExist = true
break
}
}
if !isExist && !isNew {
// deleted node itself will exit the cluster
swarm.reset()
_ = swarm.p2p.Stop()
_ = swarm.Stop()
return true
}
// update notifiee info
swarm.notifiee.mu.Lock()
swarm.notifiee.peers = vpInfos
swarm.notifiee.mu.Unlock()
swarm.notifiee.setPeers(vpInfos)
return false
}
func (swarm *Swarm) reset() {
swarm.routers = nil
swarm.multiAddrs = nil
swarm.connectedPeers = sync.Map{}
swarm.notifiee.setPeers(nil)
}
func (swarm *Swarm) Disconnect(vpInfos map[uint64]*VPInfo) {
for id, info := range vpInfos {
if err := swarm.p2p.Disconnect(info.IPAddr); err != nil {
swarm.logger.Errorf("Disconnect peer %s failed, err: %s", err.Error())
}
swarm.logger.Infof("Disconnect peer [ID: %d, Pid: %s]", id, info.IPAddr)
}
swarm.logger.Infof("======== NOTE!!! THIS NODE HAS BEEN DELETED!!!")
}

View File

@ -24,3 +24,4 @@ func UnMasherVPInfo(vpInfoBytes []byte) (*VPInfo, error) {
}

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-----