bitxhub/internal/app/bitxhub.go

190 lines
4.5 KiB
Go

package app
import (
"context"
"fmt"
"time"
"github.com/meshplus/bitxhub/pkg/order"
"github.com/common-nighthawk/go-figure"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub/internal/executor"
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/internal/ledger/genesis"
"github.com/meshplus/bitxhub/internal/loggers"
orderplg "github.com/meshplus/bitxhub/internal/plugins"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/internal/router"
"github.com/meshplus/bitxhub/internal/storages"
"github.com/meshplus/bitxhub/pkg/peermgr"
"github.com/sirupsen/logrus"
)
type BitXHub struct {
Ledger ledger.Ledger
Executor executor.Executor
Router router.Router
Order order.Order
PeerMgr peermgr.PeerManager
repo *repo.Repo
logger logrus.FieldLogger
ctx context.Context
cancel context.CancelFunc
}
func NewBitXHub(rep *repo.Repo) (*BitXHub, error) {
repoRoot := rep.Config.RepoRoot
logger := loggers.Logger(loggers.App)
if err := storages.Initialize(repoRoot); err != nil {
return nil, fmt.Errorf("storages initialize: %w", err)
}
bcStorage, err := storages.Get(storages.BlockChain)
if err != nil {
return nil, fmt.Errorf("create blockchain storage: %w", err)
}
// 0. load ledger
ldg, err := ledger.New(repoRoot, bcStorage, loggers.Logger(loggers.Executor))
if err != nil {
return nil, fmt.Errorf("create ledger: %w", err)
}
if ldg.GetChainMeta().Height == 0 {
if err := genesis.Initialize(rep.Config, ldg); err != nil {
return nil, err
}
logger.Info("Initialize genesis")
}
// 1. create executor
exec, err := executor.New(ldg, loggers.Logger(loggers.Executor))
if err != nil {
return nil, fmt.Errorf("create BlockExecutor: %w", err)
}
chainMeta := ldg.GetChainMeta()
peerMgr, err := peermgr.New(rep, loggers.Logger(loggers.P2P), ldg)
if err != nil {
return nil, fmt.Errorf("create peer manager: %w", err)
}
m := make(map[uint64]types.Address)
if !rep.Config.Solo {
for i, node := range rep.NetworkConfig.Nodes {
m[node.ID] = types.String2Address(rep.Config.Genesis.Addresses[i])
}
}
order, err := orderplg.New(
order.WithRepoRoot(repoRoot),
order.WithStoragePath(repo.GetStoragePath(repoRoot, "order")),
order.WithPluginPath(rep.Config.Plugin),
order.WithNodes(m),
order.WithID(rep.NetworkConfig.ID),
order.WithPeerManager(peerMgr),
order.WithPrivKey(nil),
order.WithLogger(loggers.Logger(loggers.Order)),
order.WithApplied(chainMeta.Height),
order.WithDigest(chainMeta.BlockHash.Hex()),
order.WithGetChainMetaFunc(ldg.GetChainMeta),
order.WithGetTransactionFunc(ldg.GetTransaction),
)
if err != nil {
return nil, err
}
r, err := router.New(loggers.Logger(loggers.Router), rep, ldg, peerMgr, order.Quorum())
if err != nil {
return nil, fmt.Errorf("create InterchainRouter: %w", err)
}
ctx, cancel := context.WithCancel(context.Background())
return &BitXHub{
repo: rep,
logger: logger,
Ledger: ldg,
Executor: exec,
Router: r,
Order: order,
PeerMgr: peerMgr,
ctx: ctx,
cancel: cancel,
}, nil
}
func (bxh *BitXHub) Start() error {
if !bxh.repo.Config.Solo {
if err := bxh.PeerMgr.Start(); err != nil {
return fmt.Errorf("peer manager start: %w", err)
}
}
if err := bxh.Order.Start(); err != nil {
return fmt.Errorf("order start: %w", err)
}
if err := bxh.Executor.Start(); err != nil {
return fmt.Errorf("executor start: %w", err)
}
if err := bxh.Router.Start(); err != nil {
return fmt.Errorf("router start: %w", err)
}
bxh.start()
bxh.printLogo()
return nil
}
func (bxh *BitXHub) Stop() error {
if err := bxh.Executor.Stop(); err != nil {
return fmt.Errorf("executor stop: %w", err)
}
if err := bxh.Router.Stop(); err != nil {
return fmt.Errorf("InterchainRouter stop: %w", err)
}
if !bxh.repo.Config.Solo {
if err := bxh.PeerMgr.Stop(); err != nil {
return fmt.Errorf("network stop: %w", err)
}
}
bxh.Order.Stop()
bxh.cancel()
bxh.logger.Info("Bitxhub stopped")
return nil
}
func (bxh *BitXHub) printLogo() {
for {
time.Sleep(100 * time.Millisecond)
if bxh.Order.Ready() {
bxh.logger.WithFields(logrus.Fields{
"plugin_path": bxh.repo.Config.Order.Plugin,
}).Info("Order is ready")
fmt.Println()
fmt.Println("=======================================================")
fig := figure.NewFigure("BitXHub", "slant", true)
fig.Print()
fmt.Println()
fmt.Println("=======================================================")
fmt.Println()
return
}
}
}