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 }