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.

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