feat(rpc): add json rpc

This commit is contained in:
zhourong 2021-03-31 20:31:45 +08:00
parent d27fa23065
commit da866a34fe
14 changed files with 762 additions and 2 deletions

61
api/jsonrpc/apis.go Normal file
View File

@ -0,0 +1,61 @@
package jsonrpc
import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/meshplus/bitxhub/api/jsonrpc/namespaces/eth"
"github.com/meshplus/bitxhub/api/jsonrpc/namespaces/net"
"github.com/meshplus/bitxhub/api/jsonrpc/namespaces/web3"
"github.com/meshplus/bitxhub/internal/coreapi/api"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/sirupsen/logrus"
)
// RPC namespaces and API version
const (
Web3Namespace = "web3"
EthNamespace = "eth"
PersonalNamespace = "personal"
NetNamespace = "net"
flagRPCAPI = "rpc-api"
apiVersion = "1.0"
)
// GetAPIs returns the list of all APIs from the Ethereum namespaces
func GetAPIs(config *repo.Config, api api.CoreAPI, logger logrus.FieldLogger) ([]rpc.API, error) {
var apis []rpc.API
ethAPI, err := eth.NewAPI(config, api, logger)
if err != nil {
return nil, err
}
apis = append(apis,
rpc.API{
Namespace: EthNamespace,
Version: apiVersion,
Service: ethAPI,
Public: true,
},
)
apis = append(apis,
rpc.API{
Namespace: Web3Namespace,
Version: apiVersion,
Service: web3.NewAPI(),
Public: true,
},
)
apis = append(apis,
rpc.API{
Namespace: NetNamespace,
Version: apiVersion,
Service: net.NewAPI(config),
Public: true,
},
)
return apis, nil
}

82
api/jsonrpc/broker.go Normal file
View File

@ -0,0 +1,82 @@
package jsonrpc
import (
"context"
"fmt"
"net/http"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/mux"
"github.com/meshplus/bitxhub/internal/coreapi/api"
"github.com/meshplus/bitxhub/internal/loggers"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/sirupsen/logrus"
)
type ChainBrokerService struct {
config *repo.Config
genesis *repo.Genesis
api api.CoreAPI
server *rpc.Server
logger logrus.FieldLogger
ctx context.Context
cancel context.CancelFunc
}
func NewChainBrokerService(coreAPI api.CoreAPI, config *repo.Config) (*ChainBrokerService, error) {
server := rpc.NewServer()
logger := loggers.Logger(loggers.API)
apis, err := GetAPIs(config, coreAPI, logger)
if err != nil {
return nil, err
}
// Register all the APIs exposed by the namespace services
for _, api := range apis {
if err := server.RegisterName(api.Namespace, api.Service); err != nil {
return nil, err
}
}
ctx, cancel := context.WithCancel(context.Background())
return &ChainBrokerService{
logger: logger,
config: config,
api: coreAPI,
server: server,
ctx: ctx,
cancel: cancel,
}, nil
}
func (cbs *ChainBrokerService) Start() error {
router := mux.NewRouter()
router.Handle("/", cbs.server)
go func() {
if err := http.ListenAndServe(fmt.Sprintf(":%d", cbs.config.Port.JsonRpc), router); err != nil {
cbs.logger.WithFields(logrus.Fields{
"error": err.Error(),
}).Error("Failed to start JSON_RPC service")
return
}
cbs.logger.WithFields(logrus.Fields{
"port": cbs.config.Port.JsonRpc,
}).Info("JSON-RPC service started")
}()
return nil
}
func (cbs *ChainBrokerService) Stop() error {
cbs.cancel()
cbs.logger.Info("GRPC service stopped")
return nil
}

View File

@ -0,0 +1,279 @@
package eth
import (
"context"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/meshplus/bitxhub-kit/types"
types2 "github.com/meshplus/bitxhub/api/jsonrpc/types"
"github.com/meshplus/bitxhub/internal/coreapi/api"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/sirupsen/logrus"
)
// PublicEthereumAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicEthereumAPI struct {
ctx context.Context
cancel context.CancelFunc
chainIDEpoch *big.Int
logger logrus.FieldLogger
api api.CoreAPI
}
// NewAPI creates an instance of the public ETH Web3 API.
func NewAPI(config *repo.Config, api api.CoreAPI, logger logrus.FieldLogger) (*PublicEthereumAPI, error) {
epoch, err := types2.ParseChainID(config.Genesis.ChainID)
if err != nil {
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
return &PublicEthereumAPI{
ctx: ctx,
cancel: cancel,
chainIDEpoch: epoch,
logger: logger,
api: api,
}, nil
}
// ProtocolVersion returns the supported Ethereum protocol version.
func (api *PublicEthereumAPI) ProtocolVersion() hexutil.Uint {
api.logger.Debug("eth_protocolVersion")
return hexutil.Uint(types2.ProtocolVersion)
}
// ChainId returns the chain's identifier in hex format
func (api *PublicEthereumAPI) ChainId() (hexutil.Uint, error) { // nolint
api.logger.Debug("eth_chainId")
return hexutil.Uint(uint(api.chainIDEpoch.Uint64())), nil
}
// Syncing returns whether or not the current node is syncing with other peers. Returns false if not, or a struct
// outlining the state of the sync if it is.
func (api *PublicEthereumAPI) Syncing() (interface{}, error) {
api.logger.Debug("eth_syncing")
// TODO
return nil, nil
}
// Mining returns whether or not this node is currently mining. Always false.
func (api *PublicEthereumAPI) Mining() bool {
api.logger.Debug("eth_mining")
return false
}
// Hashrate returns the current node's hashrate. Always 0.
func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
api.logger.Debug("eth_hashrate")
return 0
}
// GasPrice returns the current gas price based on Ethermint's gas price oracle.
func (api *PublicEthereumAPI) GasPrice() *hexutil.Big {
api.logger.Debug("eth_gasPrice")
out := big.NewInt(0)
return (*hexutil.Big)(out)
}
// BlockNumber returns the current block number.
func (api *PublicEthereumAPI) BlockNumber() (hexutil.Uint64, error) {
api.logger.Debug("eth_blockNumber")
meta, err := api.api.Chain().Meta()
if err != nil {
return 0, err
}
return hexutil.Uint64(meta.Height), nil
}
// GetBalance returns the provided account's balance up to the provided block number.
func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum types2.BlockNumber) (*hexutil.Big, error) {
api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum)
if blockNum != types2.LatestBlockNumber {
return nil, fmt.Errorf("only support query for latest block number")
}
account := api.api.Account().GetAccount(types.NewAddress(address.Bytes()))
balance := account.GetBalance()
return (*hexutil.Big)(big.NewInt(int64(balance))), nil
}
// GetStorageAt returns the contract storage at the given address, block number, and key.
func (api *PublicEthereumAPI) GetStorageAt(address common.Address, key string, blockNum types2.BlockNumber) (hexutil.Bytes, error) {
api.logger.Debug("eth_getStorageAt", "address", address, "key", key, "block number", blockNum)
if blockNum != types2.LatestBlockNumber {
return nil, fmt.Errorf("only support query for latest block number")
}
account := api.api.Account().GetAccount(types.NewAddress(address.Bytes()))
ok, val := account.GetState([]byte(key))
if !ok {
return nil, nil
}
return val, nil
}
// GetTransactionCount returns the number of transactions at the given address up to the given block number.
func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockNum types2.BlockNumber) (*hexutil.Uint64, error) {
api.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum)
if blockNum != types2.LatestBlockNumber {
return nil, fmt.Errorf("only support query for latest block number")
}
account := api.api.Account().GetAccount(types.NewAddress(address.Bytes()))
nonce := account.GetNonce()
return (*hexutil.Uint64)(&nonce), nil
}
// GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash.
func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint {
api.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash)
return nil
}
// GetBlockTransactionCountByNumber returns the number of transactions in the block identified by its height.
func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum uint64) *hexutil.Uint {
api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum)
return nil
}
// GetUncleCountByBlockHash returns the number of uncles in the block idenfied by hash. Always zero.
func (api *PublicEthereumAPI) GetUncleCountByBlockHash(_ common.Hash) hexutil.Uint {
return 0
}
func (api *PublicEthereumAPI) GetUncleCountByBlockNumber(_ uint64) hexutil.Uint {
return 0
}
// GetCode returns the contract code at the given address and block number.
func (api *PublicEthereumAPI) GetCode(address common.Address, blockNumber types2.BlockNumber) (hexutil.Bytes, error) {
api.logger.Debug("eth_getCode", "address", address, "block number", blockNumber)
if blockNumber != types2.LatestBlockNumber {
return nil, fmt.Errorf("only support query for latest block number")
}
account := api.api.Account().GetAccount(types.NewAddress(address.Bytes()))
code := account.Code()
return code, nil
}
// GetTransactionLogs returns the logs given a transaction hash.
func (api *PublicEthereumAPI) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error) {
api.logger.Debug("eth_getTransactionLogs", "hash", txHash)
// TODO
return nil, nil
}
// SendRawTransaction send a raw Ethereum transaction.
func (api *PublicEthereumAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) {
api.logger.Debug("eth_sendRawTransaction", "data", data)
// TODO
return common.Hash{}, nil
}
// Call performs a raw contract call.
func (api *PublicEthereumAPI) Call(args types2.CallArgs, blockNr uint64, _ *map[common.Address]types2.Account) (hexutil.Bytes, error) {
api.logger.Debug("eth_call", "args", args, "block number", blockNr)
// TODO
return nil, nil
}
// EstimateGas returns an estimate of gas usage for the given smart contract call.
// It adds 1,000 gas to the returned value instead of using the gas adjustment
// param from the SDK.
func (api *PublicEthereumAPI) EstimateGas(args types2.CallArgs) (hexutil.Uint64, error) {
api.logger.Debug("eth_estimateGas", "args", args)
// TODO
return hexutil.Uint64(1000), nil
}
// GetBlockByHash returns the block identified by hash.
func (api *PublicEthereumAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
api.logger.Debug("eth_getBlockByHash", "hash", hash, "full", fullTx)
// TODO
return nil, nil
}
// GetBlockByNumber returns the block identified by number.
func (api *PublicEthereumAPI) GetBlockByNumber(blockNum uint64, fullTx bool) (map[string]interface{}, error) {
api.logger.Debug("eth_getBlockByNumber", "number", blockNum, "full", fullTx)
// TODO
return nil, nil
}
// GetTransactionByHash returns the transaction identified by hash.
func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*types2.Transaction, error) {
api.logger.Debug("eth_getTransactionByHash", "hash", hash)
// TODO
return nil, nil
}
// GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index.
func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*types2.Transaction, error) {
api.logger.Debug("eth_getTransactionByHashAndIndex", "hash", hash, "index", idx)
// TODO
return nil, nil
}
// GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index.
func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum uint64, idx hexutil.Uint) (*types2.Transaction, error) {
api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
// TODO
return nil, nil
}
// GetTransactionReceipt returns the transaction receipt identified by hash.
func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
api.logger.Debug("eth_getTransactionReceipt", "hash", hash)
// TODO
return nil, nil
}
// PendingTransactions returns the transactions that are in the transaction pool
// and have a from address that is one of the accounts this node manages.
func (api *PublicEthereumAPI) PendingTransactions() ([]*types2.Transaction, error) {
api.logger.Debug("eth_pendingTransactions")
return nil, nil
}
// GetUncleByBlockHashAndIndex returns the uncle identified by hash and index. Always returns nil.
func (api *PublicEthereumAPI) GetUncleByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) map[string]interface{} {
return nil
}
// GetUncleByBlockNumberAndIndex returns the uncle identified by number and index. Always returns nil.
func (api *PublicEthereumAPI) GetUncleByBlockNumberAndIndex(number hexutil.Uint, idx hexutil.Uint) map[string]interface{} {
return nil
}

View File

@ -0,0 +1,31 @@
package net
import (
"fmt"
"github.com/meshplus/bitxhub/api/jsonrpc/types"
"github.com/meshplus/bitxhub/internal/repo"
)
// PublicNetAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicNetAPI struct {
networkVersion uint64
}
// NewAPI creates an instance of the public Net Web3 API.
func NewAPI(config *repo.Config) *PublicNetAPI {
// parse the chainID from a integer string
chainIDEpoch, err := types.ParseChainID(config.ChainID)
if err != nil {
panic(err)
}
return &PublicNetAPI{
networkVersion: chainIDEpoch.Uint64(),
}
}
// Version returns the current ethereum protocol version.
func (api *PublicNetAPI) Version() string {
return fmt.Sprintf("%d", api.networkVersion)
}

View File

@ -0,0 +1,27 @@
package web3
import (
"fmt"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/meshplus/bitxhub"
)
// PublicWeb3API is the web3_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicWeb3API struct{}
// NewAPI creates an instance of the Web3 API.
func NewAPI() *PublicWeb3API {
return &PublicWeb3API{}
}
// ClientVersion returns the client version in the Web3 user agent format.
func (PublicWeb3API) ClientVersion() string {
return fmt.Sprintf("%s-%s-%s", bitxhub.CurrentVersion, bitxhub.CurrentBranch, bitxhub.CurrentCommit)
}
// Sha3 returns the keccak-256 hash of the passed-in input.
func (PublicWeb3API) Sha3(input hexutil.Bytes) hexutil.Bytes {
return crypto.Keccak256(input)
}

View File

@ -0,0 +1,38 @@
package types
import (
"sync"
"github.com/ethereum/go-ethereum/common"
)
// AddrLocker is a mutex structure used to avoid querying outdated account data
type AddrLocker struct {
mu sync.Mutex
locks map[common.Address]*sync.Mutex
}
// lock returns the lock of the given address.
func (l *AddrLocker) lock(address common.Address) *sync.Mutex {
l.mu.Lock()
defer l.mu.Unlock()
if l.locks == nil {
l.locks = make(map[common.Address]*sync.Mutex)
}
if _, ok := l.locks[address]; !ok {
l.locks[address] = new(sync.Mutex)
}
return l.locks[address]
}
// LockAddr locks an account's mutex. This is used to prevent another tx getting the
// same nonce until the lock is released. The mutex prevents the (an identical nonce) from
// being read again during the time that the first transaction is being signed.
func (l *AddrLocker) LockAddr(address common.Address) {
l.lock(address).Lock()
}
// UnlockAddr unlocks the mutex of the given account.
func (l *AddrLocker) UnlockAddr(address common.Address) {
l.lock(address).Unlock()
}

View File

@ -0,0 +1,81 @@
package types
import (
"fmt"
"math"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// BlockNumber represents decoding hex string to block values
type BlockNumber int64
const (
// LatestBlockNumber mapping from "latest" to 0 for tm query
LatestBlockNumber = BlockNumber(0)
// EarliestBlockNumber mapping from "earliest" to 1 for tm query (earliest query not supported)
EarliestBlockNumber = BlockNumber(1)
// PendingBlockNumber mapping from "pending" to -1 for tm query
PendingBlockNumber = BlockNumber(-1)
)
// NewBlockNumber creates a new BlockNumber instance.
func NewBlockNumber(n *big.Int) BlockNumber {
return BlockNumber(n.Int64())
}
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
// - "latest", "earliest" or "pending" as string arguments
// - the block number
// Returned errors:
// - an invalid block number error when the given argument isn't a known strings
// - an out of range error when the given block number is either too little or too large
func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
input := strings.TrimSpace(string(data))
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
input = input[1 : len(input)-1]
}
switch input {
case "earliest":
*bn = EarliestBlockNumber
return nil
case "latest":
*bn = LatestBlockNumber
return nil
case "pending":
*bn = PendingBlockNumber
return nil
}
blckNum, err := hexutil.DecodeUint64(input)
if err != nil {
return err
}
if blckNum > math.MaxInt64 {
return fmt.Errorf("blocknumber too high")
}
*bn = BlockNumber(blckNum)
return nil
}
// Int64 converts block number to primitive type
func (bn BlockNumber) Int64() int64 {
return int64(bn)
}
// TmHeight is a util function used for the Tendermint RPC client. It returns
// nil if the block number is "latest". Otherwise, it returns the pointer of the
// int64 value of the height.
func (bn BlockNumber) TmHeight() *int64 {
if bn == LatestBlockNumber {
return nil
}
height := bn.Int64()
return &height
}

View File

@ -0,0 +1,52 @@
package types
import (
"fmt"
"math/big"
"math/rand"
"regexp"
"strings"
)
var (
regexChainID = `[a-z]*`
regexSeparator = `-{1}`
regexEpoch = `[1-9][0-9]*`
ethermintChainID = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, regexChainID, regexSeparator, regexEpoch))
)
// IsValidChainID returns false if the given chain identifier is incorrectly formatted.
func IsValidChainID(chainID string) bool {
if len(chainID) > 48 {
return false
}
return ethermintChainID.MatchString(chainID)
}
// ParseChainID parses a string chain identifier's epoch to an Ethereum-compatible
// chain-id in *big.Int format. The function returns an error if the chain-id has an invalid format
func ParseChainID(chainID string) (*big.Int, error) {
chainID = strings.TrimSpace(chainID)
if len(chainID) > 48 {
return nil, fmt.Errorf("chain-id '%s' cannot exceed 48 chars", chainID)
}
matches := ethermintChainID.FindStringSubmatch(chainID)
if matches == nil || len(matches) != 3 || matches[1] == "" {
return nil, fmt.Errorf("invalid chain-id: %s", chainID)
}
// verify that the chain-id entered is a base 10 integer
chainIDInt, ok := new(big.Int).SetString(matches[2], 10)
if !ok {
return nil, fmt.Errorf("invalid chain-id, epoch %s must be base-10 integer format", matches[2])
}
return chainIDInt, nil
}
// GenerateRandomChainID returns a random chain-id in the valid format.
func GenerateRandomChainID() string {
return fmt.Sprintf("ethermint-%d", 10+rand.Intn(10000))
}

View File

@ -0,0 +1,93 @@
package types
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// Copied the Account and StorageResult types since they are registered under an
// internal pkg on geth.
// Constants to match up protocol versions and messages
const (
eth65 = 65
// ProtocolVersion is the latest supported version of the eth protocol.
ProtocolVersion = eth65
)
// AccountResult struct for account proof
type AccountResult struct {
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *hexutil.Big `json:"balance"`
CodeHash common.Hash `json:"codeHash"`
Nonce hexutil.Uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
StorageProof []StorageResult `json:"storageProof"`
}
// StorageResult defines the format for storage proof return
type StorageResult struct {
Key string `json:"key"`
Value *hexutil.Big `json:"value"`
Proof []string `json:"proof"`
}
// Transaction represents a transaction returned to RPC clients.
type Transaction struct {
BlockHash *common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
Nonce hexutil.Uint64 `json:"nonce"`
To *common.Address `json:"to"`
TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
Value *hexutil.Big `json:"value"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
}
// SendTxArgs represents the arguments to submit a new transaction into the transaction pool.
// Duplicate struct definition since geth struct is in internal package
// Ref: https://github.com/ethereum/go-ethereum/blob/release/1.9/internal/ethapi/api.go#L1346
type SendTxArgs struct {
From common.Address `json:"from"`
To *common.Address `json:"to"`
Gas *hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Value *hexutil.Big `json:"value"`
Nonce *hexutil.Uint64 `json:"nonce"`
// We accept "data" and "input" for backwards-compatibility reasons. "input" is the
// newer name and should be preferred by clients.
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input"`
}
// CallArgs represents the arguments for a call.
type CallArgs struct {
From *common.Address `json:"from"`
To *common.Address `json:"to"`
Gas *hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Value *hexutil.Big `json:"value"`
Data *hexutil.Bytes `json:"data"`
}
// Account indicates the overriding fields of account during the execution of
// a message call.
// NOTE: state and stateDiff can't be specified at the same time. If state is
// set, message execution will only use the data in the given state. Otherwise
// if statDiff is set, all diff will be applied first and then execute the call
// message.
type Account struct {
Nonce *hexutil.Uint64 `json:"nonce"`
Code *hexutil.Bytes `json:"code"`
Balance **hexutil.Big `json:"balance"`
State *map[common.Hash]common.Hash `json:"state"`
StateDiff *map[common.Hash]common.Hash `json:"stateDiff"`
}

View File

@ -16,11 +16,11 @@ import (
"github.com/meshplus/bitxhub-kit/log" "github.com/meshplus/bitxhub-kit/log"
"github.com/meshplus/bitxhub/api/gateway" "github.com/meshplus/bitxhub/api/gateway"
"github.com/meshplus/bitxhub/api/grpc" "github.com/meshplus/bitxhub/api/grpc"
"github.com/meshplus/bitxhub/api/jsonrpc"
"github.com/meshplus/bitxhub/internal/app" "github.com/meshplus/bitxhub/internal/app"
"github.com/meshplus/bitxhub/internal/coreapi" "github.com/meshplus/bitxhub/internal/coreapi"
"github.com/meshplus/bitxhub/internal/loggers" "github.com/meshplus/bitxhub/internal/loggers"
"github.com/meshplus/bitxhub/internal/repo" "github.com/meshplus/bitxhub/internal/repo"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -96,6 +96,16 @@ func start(ctx *cli.Context) error {
return err return err
} }
// start json-rpc service
cbs, err := jsonrpc.NewChainBrokerService(api, repo.Config)
if err != nil {
return err
}
if err := cbs.Start(); err != nil {
return err
}
go func() { go func() {
logger.WithField("port", repo.Config.Port.Gateway).Info("Gateway service started") logger.WithField("port", repo.Config.Port.Gateway).Info("Gateway service started")
err := gateway.Start(repo.Config) err := gateway.Start(repo.Config)

View File

@ -3,6 +3,7 @@ title = "BitXHub configuration file"
solo = false solo = false
[port] [port]
jsonrpc = 8881
grpc = 60011 grpc = 60011
gateway = 9091 gateway = 9091
pprof = 53121 pprof = 53121
@ -44,7 +45,7 @@ solo = false
consensus = "info" consensus = "info"
executor = "info" executor = "info"
router = "info" router = "info"
api = "info" api = "debug"
coreapi = "info" coreapi = "info"
storage = "info" storage = "info"
@ -61,6 +62,7 @@ solo = false
type = "serial" # opensource version only supports serial type, commercial version supports serial and parallel types type = "serial" # opensource version only supports serial type, commercial version supports serial and parallel types
[genesis] [genesis]
chainid = "a-1"
dider = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013" dider = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
[[genesis.admins]] [[genesis.admins]]
address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013" address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"

1
go.mod
View File

@ -15,6 +15,7 @@ require (
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/golang/mock v1.5.0 github.com/golang/mock v1.5.0
github.com/google/btree v1.0.0 github.com/google/btree v1.0.0
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0

View File

@ -53,6 +53,7 @@ type Security struct {
} }
type Port struct { type Port struct {
JsonRpc int64 `toml:"jsonrpc" json:"jsonrpc"`
Grpc int64 `toml:"grpc" json:"grpc"` Grpc int64 `toml:"grpc" json:"grpc"`
Gateway int64 `toml:"gateway" json:"gateway"` Gateway int64 `toml:"gateway" json:"gateway"`
PProf int64 `toml:"pprof" json:"pprof"` PProf int64 `toml:"pprof" json:"pprof"`
@ -104,6 +105,7 @@ type LogModule struct {
} }
type Genesis struct { type Genesis struct {
ChainID string `json:"chainid" toml:"chainid"`
Admins []*Admin `json:"admins" toml:"admins"` Admins []*Admin `json:"admins" toml:"admins"`
Strategy map[string]string `json:"strategy" toml:"strategy"` Strategy map[string]string `json:"strategy" toml:"strategy"`
Dider string `json:"dider" toml:"dider"` Dider string `json:"dider" toml:"dider"`

View File

@ -49,6 +49,7 @@ function prepare() {
x_replace "s/9091/909${i}/g" "${bitxhubConfig}" x_replace "s/9091/909${i}/g" "${bitxhubConfig}"
x_replace "s/53121/5312${i}/g" "${bitxhubConfig}" x_replace "s/53121/5312${i}/g" "${bitxhubConfig}"
x_replace "s/40011/4001${i}/g" "${bitxhubConfig}" x_replace "s/40011/4001${i}/g" "${bitxhubConfig}"
x_replace "s/8881/888${i}/g" "${bitxhubConfig}"
x_replace "1s/1/${i}/" "${networkConfig}" x_replace "1s/1/${i}/" "${networkConfig}"
done done