snapshot.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright 2017 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 parlia
  17. import (
  18. "bytes"
  19. "encoding/hex"
  20. "encoding/json"
  21. "errors"
  22. "math/big"
  23. "sort"
  24. "github.com/ethereum/go-ethereum/common"
  25. "github.com/ethereum/go-ethereum/consensus"
  26. "github.com/ethereum/go-ethereum/core/types"
  27. "github.com/ethereum/go-ethereum/ethdb"
  28. "github.com/ethereum/go-ethereum/internal/ethapi"
  29. "github.com/ethereum/go-ethereum/params"
  30. lru "github.com/hashicorp/golang-lru"
  31. )
  32. // Snapshot is the state of the validatorSet at a given point.
  33. type Snapshot struct {
  34. config *params.ParliaConfig // Consensus engine parameters to fine tune behavior
  35. ethAPI *ethapi.PublicBlockChainAPI
  36. sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
  37. Number uint64 `json:"number"` // Block number where the snapshot was created
  38. Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
  39. Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment
  40. Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections
  41. RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash
  42. }
  43. // newSnapshot creates a new snapshot with the specified startup parameters. This
  44. // method does not initialize the set of recent validators, so only ever use it for
  45. // the genesis block.
  46. func newSnapshot(
  47. config *params.ParliaConfig,
  48. sigCache *lru.ARCCache,
  49. number uint64,
  50. hash common.Hash,
  51. validators []common.Address,
  52. ethAPI *ethapi.PublicBlockChainAPI,
  53. ) *Snapshot {
  54. snap := &Snapshot{
  55. config: config,
  56. ethAPI: ethAPI,
  57. sigCache: sigCache,
  58. Number: number,
  59. Hash: hash,
  60. Recents: make(map[uint64]common.Address),
  61. RecentForkHashes: make(map[uint64]string),
  62. Validators: make(map[common.Address]struct{}),
  63. }
  64. for _, v := range validators {
  65. snap.Validators[v] = struct{}{}
  66. }
  67. return snap
  68. }
  69. // validatorsAscending implements the sort interface to allow sorting a list of addresses
  70. type validatorsAscending []common.Address
  71. func (s validatorsAscending) Len() int { return len(s) }
  72. func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 }
  73. func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  74. // loadSnapshot loads an existing snapshot from the database.
  75. func loadSnapshot(config *params.ParliaConfig, sigCache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) {
  76. blob, err := db.Get(append([]byte("parlia-"), hash[:]...))
  77. if err != nil {
  78. return nil, err
  79. }
  80. snap := new(Snapshot)
  81. if err := json.Unmarshal(blob, snap); err != nil {
  82. return nil, err
  83. }
  84. snap.config = config
  85. snap.sigCache = sigCache
  86. snap.ethAPI = ethAPI
  87. return snap, nil
  88. }
  89. // store inserts the snapshot into the database.
  90. func (s *Snapshot) store(db ethdb.Database) error {
  91. blob, err := json.Marshal(s)
  92. if err != nil {
  93. return err
  94. }
  95. return db.Put(append([]byte("parlia-"), s.Hash[:]...), blob)
  96. }
  97. // copy creates a deep copy of the snapshot
  98. func (s *Snapshot) copy() *Snapshot {
  99. cpy := &Snapshot{
  100. config: s.config,
  101. ethAPI: s.ethAPI,
  102. sigCache: s.sigCache,
  103. Number: s.Number,
  104. Hash: s.Hash,
  105. Validators: make(map[common.Address]struct{}),
  106. Recents: make(map[uint64]common.Address),
  107. RecentForkHashes: make(map[uint64]string),
  108. }
  109. for v := range s.Validators {
  110. cpy.Validators[v] = struct{}{}
  111. }
  112. for block, v := range s.Recents {
  113. cpy.Recents[block] = v
  114. }
  115. for block, id := range s.RecentForkHashes {
  116. cpy.RecentForkHashes[block] = id
  117. }
  118. return cpy
  119. }
  120. func (s *Snapshot) isMajorityFork(forkHash string) bool {
  121. ally := 0
  122. for _, h := range s.RecentForkHashes {
  123. if h == forkHash {
  124. ally++
  125. }
  126. }
  127. return ally > len(s.RecentForkHashes)/2
  128. }
  129. func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) {
  130. // Allow passing in no headers for cleaner code
  131. if len(headers) == 0 {
  132. return s, nil
  133. }
  134. // Sanity check that the headers can be applied
  135. for i := 0; i < len(headers)-1; i++ {
  136. if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 {
  137. return nil, errOutOfRangeChain
  138. }
  139. if !bytes.Equal(headers[i+1].ParentHash.Bytes(), headers[i].Hash().Bytes()) {
  140. return nil, errBlockHashInconsistent
  141. }
  142. }
  143. if headers[0].Number.Uint64() != s.Number+1 {
  144. return nil, errOutOfRangeChain
  145. }
  146. if !bytes.Equal(headers[0].ParentHash.Bytes(), s.Hash.Bytes()) {
  147. return nil, errBlockHashInconsistent
  148. }
  149. // Iterate through the headers and create a new snapshot
  150. snap := s.copy()
  151. for _, header := range headers {
  152. number := header.Number.Uint64()
  153. // Delete the oldest validator from the recent list to allow it signing again
  154. if limit := uint64(len(snap.Validators)/2 + 1); number >= limit {
  155. delete(snap.Recents, number-limit)
  156. }
  157. if limit := uint64(len(snap.Validators)); number >= limit {
  158. delete(snap.RecentForkHashes, number-limit)
  159. }
  160. // Resolve the authorization key and check against signers
  161. validator, err := ecrecover(header, s.sigCache, chainId)
  162. if err != nil {
  163. return nil, err
  164. }
  165. if _, ok := snap.Validators[validator]; !ok {
  166. return nil, errUnauthorizedValidator
  167. }
  168. for _, recent := range snap.Recents {
  169. if recent == validator {
  170. return nil, errRecentlySigned
  171. }
  172. }
  173. snap.Recents[number] = validator
  174. // change validator set
  175. if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) {
  176. checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents)
  177. if checkpointHeader == nil {
  178. return nil, consensus.ErrUnknownAncestor
  179. }
  180. validatorBytes := checkpointHeader.Extra[extraVanity : len(checkpointHeader.Extra)-extraSeal]
  181. // get validators from headers and use that for new validator set
  182. newValArr, err := ParseValidators(validatorBytes)
  183. if err != nil {
  184. return nil, err
  185. }
  186. newVals := make(map[common.Address]struct{}, len(newValArr))
  187. for _, val := range newValArr {
  188. newVals[val] = struct{}{}
  189. }
  190. oldLimit := len(snap.Validators)/2 + 1
  191. newLimit := len(newVals)/2 + 1
  192. if newLimit < oldLimit {
  193. for i := 0; i < oldLimit-newLimit; i++ {
  194. delete(snap.Recents, number-uint64(newLimit)-uint64(i))
  195. }
  196. }
  197. oldLimit = len(snap.Validators)
  198. newLimit = len(newVals)
  199. if newLimit < oldLimit {
  200. for i := 0; i < oldLimit-newLimit; i++ {
  201. delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i))
  202. }
  203. }
  204. snap.Validators = newVals
  205. }
  206. snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
  207. }
  208. snap.Number += uint64(len(headers))
  209. snap.Hash = headers[len(headers)-1].Hash()
  210. return snap, nil
  211. }
  212. // validators retrieves the list of validators in ascending order.
  213. func (s *Snapshot) validators() []common.Address {
  214. validators := make([]common.Address, 0, len(s.Validators))
  215. for v := range s.Validators {
  216. validators = append(validators, v)
  217. }
  218. sort.Sort(validatorsAscending(validators))
  219. return validators
  220. }
  221. // inturn returns if a validator at a given block height is in-turn or not.
  222. func (s *Snapshot) inturn(validator common.Address) bool {
  223. validators := s.validators()
  224. offset := (s.Number + 1) % uint64(len(validators))
  225. return validators[offset] == validator
  226. }
  227. func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool {
  228. idx := s.indexOfVal(validator)
  229. if idx < 0 {
  230. return true
  231. }
  232. validatorNum := int64(len(s.validators()))
  233. if validatorNum == 1 {
  234. return true
  235. }
  236. if validator == header.Coinbase {
  237. return false
  238. }
  239. offset := (int64(s.Number) + 1) % validatorNum
  240. if int64(idx) >= offset {
  241. return int64(idx)-offset >= validatorNum-2
  242. } else {
  243. return validatorNum+int64(idx)-offset >= validatorNum-2
  244. }
  245. }
  246. func (s *Snapshot) indexOfVal(validator common.Address) int {
  247. validators := s.validators()
  248. for idx, val := range validators {
  249. if val == validator {
  250. return idx
  251. }
  252. }
  253. return -1
  254. }
  255. func (s *Snapshot) supposeValidator() common.Address {
  256. validators := s.validators()
  257. index := (s.Number + 1) % uint64(len(validators))
  258. return validators[index]
  259. }
  260. func ParseValidators(validatorsBytes []byte) ([]common.Address, error) {
  261. if len(validatorsBytes)%validatorBytesLength != 0 {
  262. return nil, errors.New("invalid validators bytes")
  263. }
  264. n := len(validatorsBytes) / validatorBytesLength
  265. result := make([]common.Address, n)
  266. for i := 0; i < n; i++ {
  267. address := make([]byte, validatorBytesLength)
  268. copy(address, validatorsBytes[i*validatorBytesLength:(i+1)*validatorBytesLength])
  269. result[i] = common.BytesToAddress(address)
  270. }
  271. return result, nil
  272. }
  273. func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header {
  274. ancient := header
  275. for i := uint64(1); i <= ite; i++ {
  276. parentHash := ancient.ParentHash
  277. parentHeight := ancient.Number.Uint64() - 1
  278. found := false
  279. if len(candidateParents) > 0 {
  280. index := sort.Search(len(candidateParents), func(i int) bool {
  281. return candidateParents[i].Number.Uint64() >= parentHeight
  282. })
  283. if index < len(candidateParents) && candidateParents[index].Number.Uint64() == parentHeight &&
  284. candidateParents[index].Hash() == parentHash {
  285. ancient = candidateParents[index]
  286. found = true
  287. }
  288. }
  289. if !found {
  290. ancient = chain.GetHeader(parentHash, parentHeight)
  291. found = true
  292. }
  293. if ancient == nil || !found {
  294. return nil
  295. }
  296. }
  297. return ancient
  298. }