You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

554 lines
15 KiB

  1. //nolint: gosec
  2. package e2e
  3. import (
  4. "errors"
  5. "fmt"
  6. "io"
  7. "math/rand"
  8. "net"
  9. "path/filepath"
  10. "sort"
  11. "strconv"
  12. "strings"
  13. "github.com/tendermint/tendermint/crypto"
  14. "github.com/tendermint/tendermint/crypto/ed25519"
  15. "github.com/tendermint/tendermint/crypto/secp256k1"
  16. rpchttp "github.com/tendermint/tendermint/rpc/client/http"
  17. mcs "github.com/tendermint/tendermint/test/maverick/consensus"
  18. )
  19. const (
  20. randomSeed int64 = 2308084734268
  21. proxyPortFirst uint32 = 5701
  22. networkIPv4 = "10.186.73.0/24"
  23. networkIPv6 = "fd80:b10c::/48"
  24. )
  25. type Mode string
  26. type Protocol string
  27. type Perturbation string
  28. const (
  29. ModeValidator Mode = "validator"
  30. ModeFull Mode = "full"
  31. ModeLight Mode = "light"
  32. ModeSeed Mode = "seed"
  33. ProtocolBuiltin Protocol = "builtin"
  34. ProtocolFile Protocol = "file"
  35. ProtocolGRPC Protocol = "grpc"
  36. ProtocolTCP Protocol = "tcp"
  37. ProtocolUNIX Protocol = "unix"
  38. PerturbationDisconnect Perturbation = "disconnect"
  39. PerturbationKill Perturbation = "kill"
  40. PerturbationPause Perturbation = "pause"
  41. PerturbationRestart Perturbation = "restart"
  42. )
  43. // Testnet represents a single testnet.
  44. type Testnet struct {
  45. Name string
  46. File string
  47. Dir string
  48. IP *net.IPNet
  49. InitialHeight int64
  50. InitialState map[string]string
  51. Validators map[*Node]int64
  52. ValidatorUpdates map[int64]map[*Node]int64
  53. Nodes []*Node
  54. KeyType string
  55. }
  56. // Node represents a Tendermint node in a testnet.
  57. type Node struct {
  58. Name string
  59. Testnet *Testnet
  60. Mode Mode
  61. PrivvalKey crypto.PrivKey
  62. NodeKey crypto.PrivKey
  63. IP net.IP
  64. ProxyPort uint32
  65. StartAt int64
  66. FastSync string
  67. StateSync bool
  68. Database string
  69. ABCIProtocol Protocol
  70. PrivvalProtocol Protocol
  71. PersistInterval uint64
  72. SnapshotInterval uint64
  73. RetainBlocks uint64
  74. Seeds []*Node
  75. PersistentPeers []*Node
  76. Perturbations []Perturbation
  77. Misbehaviors map[int64]string
  78. }
  79. // LoadTestnet loads a testnet from a manifest file, using the filename to
  80. // determine the testnet name and directory (from the basename of the file).
  81. // The testnet generation must be deterministic, since it is generated
  82. // separately by the runner and the test cases. For this reason, testnets use a
  83. // random seed to generate e.g. keys.
  84. func LoadTestnet(file string) (*Testnet, error) {
  85. manifest, err := LoadManifest(file)
  86. if err != nil {
  87. return nil, err
  88. }
  89. dir := strings.TrimSuffix(file, filepath.Ext(file))
  90. // Set up resource generators. These must be deterministic.
  91. netAddress := networkIPv4
  92. if manifest.IPv6 {
  93. netAddress = networkIPv6
  94. }
  95. _, ipNet, err := net.ParseCIDR(netAddress)
  96. if err != nil {
  97. return nil, fmt.Errorf("invalid IP network address %q: %w", netAddress, err)
  98. }
  99. ipGen := newIPGenerator(ipNet)
  100. keyGen := newKeyGenerator(randomSeed)
  101. proxyPortGen := newPortGenerator(proxyPortFirst)
  102. testnet := &Testnet{
  103. Name: filepath.Base(dir),
  104. File: file,
  105. Dir: dir,
  106. IP: ipGen.Network(),
  107. InitialHeight: 1,
  108. InitialState: manifest.InitialState,
  109. Validators: map[*Node]int64{},
  110. ValidatorUpdates: map[int64]map[*Node]int64{},
  111. Nodes: []*Node{},
  112. }
  113. if manifest.InitialHeight > 0 {
  114. testnet.InitialHeight = manifest.InitialHeight
  115. }
  116. // Set up nodes, in alphabetical order (IPs and ports get same order).
  117. nodeNames := []string{}
  118. for name := range manifest.Nodes {
  119. nodeNames = append(nodeNames, name)
  120. }
  121. sort.Strings(nodeNames)
  122. for _, name := range nodeNames {
  123. nodeManifest := manifest.Nodes[name]
  124. node := &Node{
  125. Name: name,
  126. Testnet: testnet,
  127. PrivvalKey: keyGen.Generate(manifest.KeyType),
  128. NodeKey: keyGen.Generate("ed25519"),
  129. IP: ipGen.Next(),
  130. ProxyPort: proxyPortGen.Next(),
  131. Mode: ModeValidator,
  132. Database: "goleveldb",
  133. ABCIProtocol: ProtocolBuiltin,
  134. PrivvalProtocol: ProtocolFile,
  135. StartAt: nodeManifest.StartAt,
  136. FastSync: nodeManifest.FastSync,
  137. StateSync: nodeManifest.StateSync,
  138. PersistInterval: 1,
  139. SnapshotInterval: nodeManifest.SnapshotInterval,
  140. RetainBlocks: nodeManifest.RetainBlocks,
  141. Perturbations: []Perturbation{},
  142. Misbehaviors: make(map[int64]string),
  143. }
  144. if node.StartAt == testnet.InitialHeight {
  145. node.StartAt = 0 // normalize to 0 for initial nodes, since code expects this
  146. }
  147. if nodeManifest.Mode != "" {
  148. node.Mode = Mode(nodeManifest.Mode)
  149. }
  150. if nodeManifest.Database != "" {
  151. node.Database = nodeManifest.Database
  152. }
  153. if nodeManifest.ABCIProtocol != "" {
  154. node.ABCIProtocol = Protocol(nodeManifest.ABCIProtocol)
  155. }
  156. if nodeManifest.PrivvalProtocol != "" {
  157. node.PrivvalProtocol = Protocol(nodeManifest.PrivvalProtocol)
  158. }
  159. if nodeManifest.PersistInterval != nil {
  160. node.PersistInterval = *nodeManifest.PersistInterval
  161. }
  162. for _, p := range nodeManifest.Perturb {
  163. node.Perturbations = append(node.Perturbations, Perturbation(p))
  164. }
  165. for heightString, misbehavior := range nodeManifest.Misbehaviors {
  166. height, err := strconv.ParseInt(heightString, 10, 64)
  167. if err != nil {
  168. return nil, fmt.Errorf("unable to parse height %s to int64: %w", heightString, err)
  169. }
  170. node.Misbehaviors[height] = misbehavior
  171. }
  172. testnet.Nodes = append(testnet.Nodes, node)
  173. }
  174. // We do a second pass to set up seeds and persistent peers, which allows graph cycles.
  175. for _, node := range testnet.Nodes {
  176. nodeManifest, ok := manifest.Nodes[node.Name]
  177. if !ok {
  178. return nil, fmt.Errorf("failed to look up manifest for node %q", node.Name)
  179. }
  180. for _, seedName := range nodeManifest.Seeds {
  181. seed := testnet.LookupNode(seedName)
  182. if seed == nil {
  183. return nil, fmt.Errorf("unknown seed %q for node %q", seedName, node.Name)
  184. }
  185. node.Seeds = append(node.Seeds, seed)
  186. }
  187. for _, peerName := range nodeManifest.PersistentPeers {
  188. peer := testnet.LookupNode(peerName)
  189. if peer == nil {
  190. return nil, fmt.Errorf("unknown persistent peer %q for node %q", peerName, node.Name)
  191. }
  192. node.PersistentPeers = append(node.PersistentPeers, peer)
  193. }
  194. // If there are no seeds or persistent peers specified, default to persistent
  195. // connections to all other nodes.
  196. if len(node.PersistentPeers) == 0 && len(node.Seeds) == 0 {
  197. for _, peer := range testnet.Nodes {
  198. if peer.Name == node.Name {
  199. continue
  200. }
  201. node.PersistentPeers = append(node.PersistentPeers, peer)
  202. }
  203. }
  204. }
  205. // Set up genesis validators. If not specified explicitly, use all validator nodes.
  206. if manifest.Validators != nil {
  207. for validatorName, power := range *manifest.Validators {
  208. validator := testnet.LookupNode(validatorName)
  209. if validator == nil {
  210. return nil, fmt.Errorf("unknown validator %q", validatorName)
  211. }
  212. testnet.Validators[validator] = power
  213. }
  214. } else {
  215. for _, node := range testnet.Nodes {
  216. if node.Mode == ModeValidator {
  217. testnet.Validators[node] = 100
  218. }
  219. }
  220. }
  221. // Set up validator updates.
  222. for heightStr, validators := range manifest.ValidatorUpdates {
  223. height, err := strconv.Atoi(heightStr)
  224. if err != nil {
  225. return nil, fmt.Errorf("invalid validator update height %q: %w", height, err)
  226. }
  227. valUpdate := map[*Node]int64{}
  228. for name, power := range validators {
  229. node := testnet.LookupNode(name)
  230. if node == nil {
  231. return nil, fmt.Errorf("unknown validator %q for update at height %v", name, height)
  232. }
  233. valUpdate[node] = power
  234. }
  235. testnet.ValidatorUpdates[int64(height)] = valUpdate
  236. }
  237. return testnet, testnet.Validate()
  238. }
  239. // Validate validates a testnet.
  240. func (t Testnet) Validate() error {
  241. if t.Name == "" {
  242. return errors.New("network has no name")
  243. }
  244. if t.IP == nil {
  245. return errors.New("network has no IP")
  246. }
  247. if len(t.Nodes) == 0 {
  248. return errors.New("network has no nodes")
  249. }
  250. for _, node := range t.Nodes {
  251. if err := node.Validate(t); err != nil {
  252. return fmt.Errorf("invalid node %q: %w", node.Name, err)
  253. }
  254. }
  255. return nil
  256. }
  257. // Validate validates a node.
  258. func (n Node) Validate(testnet Testnet) error {
  259. if n.Name == "" {
  260. return errors.New("node has no name")
  261. }
  262. if n.IP == nil {
  263. return errors.New("node has no IP address")
  264. }
  265. if !testnet.IP.Contains(n.IP) {
  266. return fmt.Errorf("node IP %v is not in testnet network %v", n.IP, testnet.IP)
  267. }
  268. if n.ProxyPort > 0 {
  269. if n.ProxyPort <= 1024 {
  270. return fmt.Errorf("local port %v must be >1024", n.ProxyPort)
  271. }
  272. for _, peer := range testnet.Nodes {
  273. if peer.Name != n.Name && peer.ProxyPort == n.ProxyPort {
  274. return fmt.Errorf("peer %q also has local port %v", peer.Name, n.ProxyPort)
  275. }
  276. }
  277. }
  278. switch n.FastSync {
  279. case "", "v0", "v1", "v2":
  280. default:
  281. return fmt.Errorf("invalid fast sync setting %q", n.FastSync)
  282. }
  283. switch n.Database {
  284. case "goleveldb", "cleveldb", "boltdb", "rocksdb", "badgerdb":
  285. default:
  286. return fmt.Errorf("invalid database setting %q", n.Database)
  287. }
  288. switch n.ABCIProtocol {
  289. case ProtocolBuiltin, ProtocolUNIX, ProtocolTCP, ProtocolGRPC:
  290. default:
  291. return fmt.Errorf("invalid ABCI protocol setting %q", n.ABCIProtocol)
  292. }
  293. if n.Mode == ModeLight && n.ABCIProtocol != ProtocolBuiltin {
  294. return errors.New("light client must use builtin protocol")
  295. }
  296. switch n.PrivvalProtocol {
  297. case ProtocolFile, ProtocolUNIX, ProtocolTCP:
  298. default:
  299. return fmt.Errorf("invalid privval protocol setting %q", n.PrivvalProtocol)
  300. }
  301. if n.StartAt > 0 && n.StartAt < n.Testnet.InitialHeight {
  302. return fmt.Errorf("cannot start at height %v lower than initial height %v",
  303. n.StartAt, n.Testnet.InitialHeight)
  304. }
  305. if n.StateSync && n.StartAt == 0 {
  306. return errors.New("state synced nodes cannot start at the initial height")
  307. }
  308. if n.PersistInterval == 0 && n.RetainBlocks > 0 {
  309. return errors.New("persist_interval=0 requires retain_blocks=0")
  310. }
  311. if n.PersistInterval > 1 && n.RetainBlocks > 0 && n.RetainBlocks < n.PersistInterval {
  312. return errors.New("persist_interval must be less than or equal to retain_blocks")
  313. }
  314. if n.SnapshotInterval > 0 && n.RetainBlocks > 0 && n.RetainBlocks < n.SnapshotInterval {
  315. return errors.New("snapshot_interval must be less than er equal to retain_blocks")
  316. }
  317. for _, perturbation := range n.Perturbations {
  318. switch perturbation {
  319. case PerturbationDisconnect, PerturbationKill, PerturbationPause, PerturbationRestart:
  320. default:
  321. return fmt.Errorf("invalid perturbation %q", perturbation)
  322. }
  323. }
  324. if (n.PrivvalProtocol != "file" || n.Mode != "validator") && len(n.Misbehaviors) != 0 {
  325. return errors.New("must be using \"file\" privval protocol to implement misbehaviors")
  326. }
  327. for height, misbehavior := range n.Misbehaviors {
  328. if height < n.StartAt {
  329. return fmt.Errorf("misbehavior height %d is below node start height %d",
  330. height, n.StartAt)
  331. }
  332. if height < testnet.InitialHeight {
  333. return fmt.Errorf("misbehavior height %d is below network initial height %d",
  334. height, testnet.InitialHeight)
  335. }
  336. exists := false
  337. for possibleBehaviors := range mcs.MisbehaviorList {
  338. if possibleBehaviors == misbehavior {
  339. exists = true
  340. }
  341. }
  342. if !exists {
  343. return fmt.Errorf("misbehavior %s does not exist", misbehavior)
  344. }
  345. }
  346. return nil
  347. }
  348. // LookupNode looks up a node by name. For now, simply do a linear search.
  349. func (t Testnet) LookupNode(name string) *Node {
  350. for _, node := range t.Nodes {
  351. if node.Name == name {
  352. return node
  353. }
  354. }
  355. return nil
  356. }
  357. // ArchiveNodes returns a list of archive nodes that start at the initial height
  358. // and contain the entire blockchain history. They are used e.g. as light client
  359. // RPC servers.
  360. func (t Testnet) ArchiveNodes() []*Node {
  361. nodes := []*Node{}
  362. for _, node := range t.Nodes {
  363. if !node.Stateless() && node.StartAt == 0 && node.RetainBlocks == 0 {
  364. nodes = append(nodes, node)
  365. }
  366. }
  367. return nodes
  368. }
  369. // RandomNode returns a random non-seed node.
  370. func (t Testnet) RandomNode() *Node {
  371. for {
  372. node := t.Nodes[rand.Intn(len(t.Nodes))]
  373. if node.Mode != ModeSeed {
  374. return node
  375. }
  376. }
  377. }
  378. // IPv6 returns true if the testnet is an IPv6 network.
  379. func (t Testnet) IPv6() bool {
  380. return t.IP.IP.To4() == nil
  381. }
  382. // HasPerturbations returns whether the network has any perturbations.
  383. func (t Testnet) HasPerturbations() bool {
  384. for _, node := range t.Nodes {
  385. if len(node.Perturbations) > 0 {
  386. return true
  387. }
  388. }
  389. return false
  390. }
  391. // LastMisbehaviorHeight returns the height of the last misbehavior.
  392. func (t Testnet) LastMisbehaviorHeight() int64 {
  393. lastHeight := int64(0)
  394. for _, node := range t.Nodes {
  395. for height := range node.Misbehaviors {
  396. if height > lastHeight {
  397. lastHeight = height
  398. }
  399. }
  400. }
  401. return lastHeight
  402. }
  403. // Address returns a P2P endpoint address for the node.
  404. func (n Node) AddressP2P(withID bool) string {
  405. ip := n.IP.String()
  406. if n.IP.To4() == nil {
  407. // IPv6 addresses must be wrapped in [] to avoid conflict with : port separator
  408. ip = fmt.Sprintf("[%v]", ip)
  409. }
  410. addr := fmt.Sprintf("%v:26656", ip)
  411. if withID {
  412. addr = fmt.Sprintf("%x@%v", n.NodeKey.PubKey().Address().Bytes(), addr)
  413. }
  414. return addr
  415. }
  416. // Address returns an RPC endpoint address for the node.
  417. func (n Node) AddressRPC() string {
  418. ip := n.IP.String()
  419. if n.IP.To4() == nil {
  420. // IPv6 addresses must be wrapped in [] to avoid conflict with : port separator
  421. ip = fmt.Sprintf("[%v]", ip)
  422. }
  423. return fmt.Sprintf("%v:26657", ip)
  424. }
  425. // Client returns an RPC client for a node.
  426. func (n Node) Client() (*rpchttp.HTTP, error) {
  427. return rpchttp.New(fmt.Sprintf("http://127.0.0.1:%v", n.ProxyPort), "/websocket")
  428. }
  429. // Stateless returns true if the node is either a seed node or a light node
  430. func (n Node) Stateless() bool {
  431. return n.Mode == ModeLight || n.Mode == ModeSeed
  432. }
  433. // keyGenerator generates pseudorandom Ed25519 keys based on a seed.
  434. type keyGenerator struct {
  435. random *rand.Rand
  436. }
  437. func newKeyGenerator(seed int64) *keyGenerator {
  438. return &keyGenerator{
  439. random: rand.New(rand.NewSource(seed)),
  440. }
  441. }
  442. func (g *keyGenerator) Generate(keyType string) crypto.PrivKey {
  443. seed := make([]byte, ed25519.SeedSize)
  444. _, err := io.ReadFull(g.random, seed)
  445. if err != nil {
  446. panic(err) // this shouldn't happen
  447. }
  448. switch keyType {
  449. case "secp256k1":
  450. return secp256k1.GenPrivKeySecp256k1(seed)
  451. case "", "ed25519":
  452. return ed25519.GenPrivKeyFromSecret(seed)
  453. default:
  454. panic("KeyType not supported") // should not make it this far
  455. }
  456. }
  457. // portGenerator generates local Docker proxy ports for each node.
  458. type portGenerator struct {
  459. nextPort uint32
  460. }
  461. func newPortGenerator(firstPort uint32) *portGenerator {
  462. return &portGenerator{nextPort: firstPort}
  463. }
  464. func (g *portGenerator) Next() uint32 {
  465. port := g.nextPort
  466. g.nextPort++
  467. if g.nextPort == 0 {
  468. panic("port overflow")
  469. }
  470. return port
  471. }
  472. // ipGenerator generates sequential IP addresses for each node, using a random
  473. // network address.
  474. type ipGenerator struct {
  475. network *net.IPNet
  476. nextIP net.IP
  477. }
  478. func newIPGenerator(network *net.IPNet) *ipGenerator {
  479. nextIP := make([]byte, len(network.IP))
  480. copy(nextIP, network.IP)
  481. gen := &ipGenerator{network: network, nextIP: nextIP}
  482. // Skip network and gateway addresses
  483. gen.Next()
  484. gen.Next()
  485. return gen
  486. }
  487. func (g *ipGenerator) Network() *net.IPNet {
  488. n := &net.IPNet{
  489. IP: make([]byte, len(g.network.IP)),
  490. Mask: make([]byte, len(g.network.Mask)),
  491. }
  492. copy(n.IP, g.network.IP)
  493. copy(n.Mask, g.network.Mask)
  494. return n
  495. }
  496. func (g *ipGenerator) Next() net.IP {
  497. ip := make([]byte, len(g.nextIP))
  498. copy(ip, g.nextIP)
  499. for i := len(g.nextIP) - 1; i >= 0; i-- {
  500. g.nextIP[i]++
  501. if g.nextIP[i] != 0 {
  502. break
  503. }
  504. }
  505. return ip
  506. }