chain.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright 2020 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package ethtest
  17. import (
  18. "compress/gzip"
  19. "encoding/json"
  20. "fmt"
  21. "io"
  22. "io/ioutil"
  23. "math/big"
  24. "os"
  25. "strings"
  26. "github.com/ethereum/go-ethereum/core"
  27. "github.com/ethereum/go-ethereum/core/forkid"
  28. "github.com/ethereum/go-ethereum/core/types"
  29. "github.com/ethereum/go-ethereum/params"
  30. "github.com/ethereum/go-ethereum/rlp"
  31. )
  32. type Chain struct {
  33. genesis core.Genesis
  34. blocks []*types.Block
  35. chainConfig *params.ChainConfig
  36. }
  37. func (c *Chain) WriteTo(writer io.Writer) error {
  38. for _, block := range c.blocks {
  39. if err := rlp.Encode(writer, block); err != nil {
  40. return err
  41. }
  42. }
  43. return nil
  44. }
  45. // Len returns the length of the chain.
  46. func (c *Chain) Len() int {
  47. return len(c.blocks)
  48. }
  49. // TD calculates the total difficulty of the chain.
  50. func (c *Chain) TD(height int) *big.Int { // TODO later on channge scheme so that the height is included in range
  51. sum := big.NewInt(0)
  52. for _, block := range c.blocks[:height] {
  53. sum.Add(sum, block.Difficulty())
  54. }
  55. return sum
  56. }
  57. // ForkID gets the fork id of the chain.
  58. func (c *Chain) ForkID() forkid.ID {
  59. return forkid.NewID(c.chainConfig, c.blocks[0].Hash(), uint64(c.Len()))
  60. }
  61. // Shorten returns a copy chain of a desired height from the imported
  62. func (c *Chain) Shorten(height int) *Chain {
  63. blocks := make([]*types.Block, height)
  64. copy(blocks, c.blocks[:height])
  65. config := *c.chainConfig
  66. return &Chain{
  67. blocks: blocks,
  68. chainConfig: &config,
  69. }
  70. }
  71. // Head returns the chain head.
  72. func (c *Chain) Head() *types.Block {
  73. return c.blocks[c.Len()-1]
  74. }
  75. func (c *Chain) GetHeaders(req GetBlockHeaders) (BlockHeaders, error) {
  76. if req.Amount < 1 {
  77. return nil, fmt.Errorf("no block headers requested")
  78. }
  79. headers := make(BlockHeaders, req.Amount)
  80. var blockNumber uint64
  81. // range over blocks to check if our chain has the requested header
  82. for _, block := range c.blocks {
  83. if block.Hash() == req.Origin.Hash || block.Number().Uint64() == req.Origin.Number {
  84. headers[0] = block.Header()
  85. blockNumber = block.Number().Uint64()
  86. }
  87. }
  88. if headers[0] == nil {
  89. return nil, fmt.Errorf("no headers found for given origin number %v, hash %v", req.Origin.Number, req.Origin.Hash)
  90. }
  91. if req.Reverse {
  92. for i := 1; i < int(req.Amount); i++ {
  93. blockNumber -= (1 - req.Skip)
  94. headers[i] = c.blocks[blockNumber].Header()
  95. }
  96. return headers, nil
  97. }
  98. for i := 1; i < int(req.Amount); i++ {
  99. blockNumber += (1 + req.Skip)
  100. headers[i] = c.blocks[blockNumber].Header()
  101. }
  102. return headers, nil
  103. }
  104. // loadChain takes the given chain.rlp file, and decodes and returns
  105. // the blocks from the file.
  106. func loadChain(chainfile string, genesis string) (*Chain, error) {
  107. gen, err := loadGenesis(genesis)
  108. if err != nil {
  109. return nil, err
  110. }
  111. gblock := gen.ToBlock(nil)
  112. blocks, err := blocksFromFile(chainfile, gblock)
  113. if err != nil {
  114. return nil, err
  115. }
  116. c := &Chain{genesis: gen, blocks: blocks, chainConfig: gen.Config}
  117. return c, nil
  118. }
  119. func loadGenesis(genesisFile string) (core.Genesis, error) {
  120. chainConfig, err := ioutil.ReadFile(genesisFile)
  121. if err != nil {
  122. return core.Genesis{}, err
  123. }
  124. var gen core.Genesis
  125. if err := json.Unmarshal(chainConfig, &gen); err != nil {
  126. return core.Genesis{}, err
  127. }
  128. return gen, nil
  129. }
  130. func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, error) {
  131. // Load chain.rlp.
  132. fh, err := os.Open(chainfile)
  133. if err != nil {
  134. return nil, err
  135. }
  136. defer fh.Close()
  137. var reader io.Reader = fh
  138. if strings.HasSuffix(chainfile, ".gz") {
  139. if reader, err = gzip.NewReader(reader); err != nil {
  140. return nil, err
  141. }
  142. }
  143. stream := rlp.NewStream(reader, 0)
  144. var blocks = make([]*types.Block, 1)
  145. blocks[0] = gblock
  146. for i := 0; ; i++ {
  147. var b types.Block
  148. if err := stream.Decode(&b); err == io.EOF {
  149. break
  150. } else if err != nil {
  151. return nil, fmt.Errorf("at block index %d: %v", i, err)
  152. }
  153. if b.NumberU64() != uint64(i+1) {
  154. return nil, fmt.Errorf("block at index %d has wrong number %d", i, b.NumberU64())
  155. }
  156. blocks = append(blocks, &b)
  157. }
  158. return blocks, nil
  159. }