forked from hyperledger-archives/burrow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
151 lines (135 loc) · 5.54 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package tendermint
import (
"fmt"
"math"
"net"
"net/url"
"strings"
"time"
"github.com/hyperledger/burrow/consensus/abci"
tmConfig "github.com/tendermint/tendermint/config"
)
const (
NeverCreateEmptyBlocks = "never"
AlwaysCreateEmptyBlocks = "always"
)
// Burrow's view on Tendermint's config. Since we operate as a Tendermint harness not all configuration values
// are applicable, we may not allow some values to specified, or we may not allow some to be set independently.
// So this serves as a layer of indirection over Tendermint's real config that we derive from ours.
type BurrowTendermintConfig struct {
Enabled bool
// Initial peers we connect to for peer exchange
Seeds string
// Whether this node should crawl the network looking for new peers - disconnecting to peers after it has shared addresses
SeedMode bool
// Peers to which we automatically connect
PersistentPeers string
ListenHost string
ListenPort string
// Optional external that nodes may provide with their NodeInfo
ExternalAddress string
// Set true for strict address routability rules
// Set false for private or local networks
AddrBookStrict bool
Moniker string
// Only accept connections from registered peers
IdentifyPeers bool
// Peers ID or address this node is authorize to sync with
AuthorizedPeers string
// EmptyBlocks mode and possible interval between empty blocks in seconds, one of:
// "", "never" (to never create unnecessary blocks)
// "always" (to create empty blocks each consensus round)
CreateEmptyBlocks string
}
func DefaultBurrowTendermintConfig() *BurrowTendermintConfig {
tmDefaultConfig := tmConfig.DefaultConfig()
url, err := url.ParseRequestURI(tmDefaultConfig.P2P.ListenAddress)
if err != nil {
return nil
}
return &BurrowTendermintConfig{
Enabled: true,
ListenHost: url.Hostname(),
ListenPort: url.Port(),
ExternalAddress: tmDefaultConfig.P2P.ExternalAddress,
CreateEmptyBlocks: "5m",
}
}
func (btc *BurrowTendermintConfig) Config(rootDir string, timeoutFactor float64) (*tmConfig.Config, error) {
conf := tmConfig.DefaultConfig()
// We expose Tendermint config as required, but try to give fewer levers to pull where possible
if btc != nil {
conf.RootDir = rootDir
conf.Mempool.RootDir = rootDir
conf.Consensus.RootDir = rootDir
// Transactions
// This creates load on leveldb for no purpose. The default indexer is "kv" and allows retrieval the TxResult
// for which we use use TxReceipt (returned from ABCI DeliverTx) - we have our own much richer index
conf.TxIndex.Indexer = "null"
conf.Mempool.MaxTxBytes = 1024 * 1024 * 4 // 4MB
// Consensus
switch strings.ToLower(btc.CreateEmptyBlocks) {
case NeverCreateEmptyBlocks, "":
conf.Consensus.CreateEmptyBlocks = false
case AlwaysCreateEmptyBlocks:
conf.Consensus.CreateEmptyBlocks = true
default:
conf.Consensus.CreateEmptyBlocks = true
createEmptyBlocksInterval, err := time.ParseDuration(btc.CreateEmptyBlocks)
if err != nil {
return nil, fmt.Errorf("could not parse CreateEmptyBlock '%s' "+
"as '%s', '%s', or duration (e.g. 1s, 2m, 4h): %v",
btc.CreateEmptyBlocks, NeverCreateEmptyBlocks, AlwaysCreateEmptyBlocks, err)
}
conf.Consensus.CreateEmptyBlocksInterval = createEmptyBlocksInterval
}
// Assume Tendermint has some mutually consistent values, assume scaling them linearly makes sense
conf.Consensus.TimeoutPropose = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutPropose)
conf.Consensus.TimeoutProposeDelta = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutProposeDelta)
conf.Consensus.TimeoutPrevote = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutPrevote)
conf.Consensus.TimeoutPrevoteDelta = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutPrevoteDelta)
conf.Consensus.TimeoutPrecommit = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutPrecommit)
conf.Consensus.TimeoutPrecommitDelta = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutPrecommitDelta)
conf.Consensus.TimeoutCommit = scaleTimeout(timeoutFactor, conf.Consensus.TimeoutCommit)
// P2P
conf.Moniker = btc.Moniker
conf.P2P.RootDir = rootDir
conf.P2P.Seeds = btc.Seeds
conf.P2P.SeedMode = btc.SeedMode
conf.P2P.PersistentPeers = btc.PersistentPeers
conf.P2P.ListenAddress = btc.ListenAddress()
conf.P2P.ExternalAddress = btc.ExternalAddress
conf.P2P.AddrBookStrict = btc.AddrBookStrict
// We use this in tests and I am not aware of a strong reason to reject nodes on the same IP with different ports
conf.P2P.AllowDuplicateIP = true
// Unfortunately this stops metrics from being used at all
conf.Instrumentation.Prometheus = false
conf.FilterPeers = btc.IdentifyPeers || btc.AuthorizedPeers != ""
}
// Disable Tendermint RPC
conf.RPC.ListenAddress = ""
return conf, nil
}
func (btc *BurrowTendermintConfig) DefaultAuthorizedPeersProvider() abci.AuthorizedPeers {
authorizedPeers := abci.NewPeerLists()
authorizedPeersAddrOrID := strings.Split(btc.AuthorizedPeers, ",")
for _, authorizedPeerAddrOrID := range authorizedPeersAddrOrID {
_, err := url.Parse(authorizedPeerAddrOrID)
isNodeAddress := err != nil
if isNodeAddress {
authorizedPeers.Addresses[authorizedPeerAddrOrID] = struct{}{}
} else {
authorizedPeers.IDs[authorizedPeerAddrOrID] = struct{}{}
}
}
return authorizedPeers
}
func scaleTimeout(factor float64, timeout time.Duration) time.Duration {
if factor == 0 {
return timeout
}
return time.Duration(math.Round(factor * float64(timeout)))
}
func (btc *BurrowTendermintConfig) ListenAddress() string {
return net.JoinHostPort(btc.ListenHost, btc.ListenPort)
}