github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/consensus/tendermint/tendermint.go (about)

     1  package tendermint
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  
     9  	"github.com/tendermint/tendermint/version"
    10  
    11  	"github.com/hyperledger/burrow/binary"
    12  	"github.com/hyperledger/burrow/consensus/abci"
    13  	"github.com/hyperledger/burrow/crypto"
    14  	"github.com/hyperledger/burrow/genesis"
    15  	"github.com/hyperledger/burrow/logging"
    16  	"github.com/hyperledger/burrow/logging/structure"
    17  	"github.com/tendermint/tendermint/config"
    18  	"github.com/tendermint/tendermint/crypto/ed25519"
    19  	"github.com/tendermint/tendermint/node"
    20  	"github.com/tendermint/tendermint/p2p"
    21  	"github.com/tendermint/tendermint/proxy"
    22  	tmTypes "github.com/tendermint/tendermint/types"
    23  	dbm "github.com/tendermint/tm-db"
    24  )
    25  
    26  func init() {
    27  	// Tendermint now sets this dynamically in it's build... we could also automate setting it
    28  	version.TMCoreSemVer = "0.34.3"
    29  }
    30  
    31  // Serves as a wrapper around the Tendermint node's closeable resources (database connections)
    32  type Node struct {
    33  	*node.Node
    34  	closers []interface {
    35  		Close() error
    36  	}
    37  }
    38  
    39  func DBProvider(ID string, backendType dbm.BackendType, dbDir string) (dbm.DB, error) {
    40  	return dbm.NewDB(ID, backendType, dbDir)
    41  }
    42  
    43  // Since Tendermint doesn't close its DB connections
    44  func (n *Node) DBProvider(ctx *node.DBContext) (dbm.DB, error) {
    45  	db, err := DBProvider(ctx.ID, dbm.BackendType(ctx.Config.DBBackend), ctx.Config.DBDir())
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	n.closers = append(n.closers, db)
    50  	return db, nil
    51  }
    52  
    53  func (n *Node) Close() {
    54  	for _, closer := range n.closers {
    55  		closer.Close()
    56  	}
    57  }
    58  
    59  func NewNode(conf *config.Config, privValidator tmTypes.PrivValidator, genesisDoc *tmTypes.GenesisDoc,
    60  	app *abci.App, metricsProvider node.MetricsProvider, logger *logging.Logger, options ...node.Option) (*Node, error) {
    61  
    62  	var err error
    63  	// disable Tendermint's RPC
    64  	conf.RPC.ListenAddress = ""
    65  
    66  	nodeKey, err := EnsureNodeKey(conf.NodeKeyFile())
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	nde := &Node{}
    72  	nde.Node, err = node.NewNode(conf, privValidator,
    73  		nodeKey, proxy.NewLocalClientCreator(app),
    74  		func() (*tmTypes.GenesisDoc, error) {
    75  			return genesisDoc, nil
    76  		},
    77  		nde.DBProvider,
    78  		metricsProvider,
    79  		NewLogger(logger.WithPrefix(structure.ComponentKey, structure.Tendermint).
    80  			With(structure.ScopeKey, "tendermint.NewNode")),
    81  		options...)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	app.SetMempoolLocker(nde.Mempool())
    86  	return nde, nil
    87  }
    88  
    89  func DeriveGenesisDoc(burrowGenesisDoc *genesis.GenesisDoc, appHash []byte) *tmTypes.GenesisDoc {
    90  	validators := make([]tmTypes.GenesisValidator, len(burrowGenesisDoc.Validators))
    91  	for i, validator := range burrowGenesisDoc.Validators {
    92  		validators[i] = tmTypes.GenesisValidator{
    93  			Address: validator.PublicKey.TendermintAddress(),
    94  			PubKey:  validator.PublicKey.TendermintPubKey(),
    95  			Name:    validator.Name,
    96  			Power:   int64(validator.Amount),
    97  		}
    98  	}
    99  	consensusParams := tmTypes.DefaultConsensusParams()
   100  	// This is the smallest increment we can use to get a strictly increasing sequence
   101  	// of block time - we set it low to avoid skew
   102  	// if the BlockTimeIota is longer than the average block time
   103  	consensusParams.Block.TimeIotaMs = 1
   104  
   105  	return &tmTypes.GenesisDoc{
   106  		ChainID:         burrowGenesisDoc.GetChainID(),
   107  		GenesisTime:     burrowGenesisDoc.GenesisTime,
   108  		Validators:      validators,
   109  		AppHash:         appHash,
   110  		ConsensusParams: consensusParams,
   111  		InitialHeight:   1,
   112  	}
   113  }
   114  
   115  func NewNodeInfo(ni p2p.DefaultNodeInfo) *NodeInfo {
   116  	address, _ := crypto.AddressFromHexString(string(ni.ID()))
   117  	return &NodeInfo{
   118  		ID:            address,
   119  		Moniker:       ni.Moniker,
   120  		ListenAddress: ni.ListenAddr,
   121  		Version:       ni.Version,
   122  		Channels:      binary.HexBytes(ni.Channels),
   123  		Network:       ni.Network,
   124  		RPCAddress:    ni.Other.RPCAddress,
   125  		TxIndex:       ni.Other.TxIndex,
   126  	}
   127  }
   128  
   129  func NewNodeKey() *p2p.NodeKey {
   130  	privKey := ed25519.GenPrivKey()
   131  	return &p2p.NodeKey{
   132  		PrivKey: privKey,
   133  	}
   134  }
   135  
   136  func WriteNodeKey(nodeKeyFile string, key json.RawMessage) error {
   137  	err := os.MkdirAll(path.Dir(nodeKeyFile), 0777)
   138  	if err != nil {
   139  		return err
   140  	}
   141  	return ioutil.WriteFile(nodeKeyFile, key, 0600)
   142  }
   143  
   144  func EnsureNodeKey(nodeKeyFile string) (*p2p.NodeKey, error) {
   145  	err := os.MkdirAll(path.Dir(nodeKeyFile), 0777)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	return p2p.LoadOrGenNodeKey(nodeKeyFile)
   151  }