engine.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. package ibftengine
  2. import (
  3. "bytes"
  4. "math/big"
  5. "time"
  6. "github.com/ethereum/go-ethereum/common"
  7. "github.com/ethereum/go-ethereum/common/hexutil"
  8. "github.com/ethereum/go-ethereum/consensus"
  9. "github.com/ethereum/go-ethereum/consensus/istanbul"
  10. istanbulcommon "github.com/ethereum/go-ethereum/consensus/istanbul/common"
  11. ibfttypes "github.com/ethereum/go-ethereum/consensus/istanbul/ibft/types"
  12. "github.com/ethereum/go-ethereum/consensus/istanbul/validator"
  13. "github.com/ethereum/go-ethereum/core/state"
  14. "github.com/ethereum/go-ethereum/core/types"
  15. "github.com/ethereum/go-ethereum/params"
  16. "github.com/ethereum/go-ethereum/rlp"
  17. "github.com/ethereum/go-ethereum/trie"
  18. "golang.org/x/crypto/sha3"
  19. )
  20. var (
  21. nilUncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
  22. nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new validator
  23. nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a validator.
  24. )
  25. type SignerFn func(data []byte) ([]byte, error)
  26. type Engine struct {
  27. cfg *istanbul.Config
  28. signer common.Address // Ethereum address of the signing key
  29. sign SignerFn // Signer function to authorize hashes with
  30. }
  31. func NewEngine(cfg *istanbul.Config, signer common.Address, sign SignerFn) *Engine {
  32. return &Engine{
  33. cfg: cfg,
  34. signer: signer,
  35. sign: sign,
  36. }
  37. }
  38. func (e *Engine) Author(header *types.Header) (common.Address, error) {
  39. // Retrieve the signature from the header extra-data
  40. extra, err := types.ExtractIstanbulExtra(header)
  41. if err != nil {
  42. return common.Address{}, err
  43. }
  44. addr, err := istanbul.GetSignatureAddress(sigHash(header).Bytes(), extra.Seal)
  45. if err != nil {
  46. return addr, err
  47. }
  48. return addr, nil
  49. }
  50. func (e *Engine) CommitHeader(header *types.Header, seals [][]byte, round *big.Int) error {
  51. // Append seals into extra-data
  52. return writeCommittedSeals(header, seals)
  53. }
  54. func (e *Engine) VerifyBlockProposal(chain consensus.ChainHeaderReader, block *types.Block, validators istanbul.ValidatorSet) (time.Duration, error) {
  55. // check block body
  56. txnHash := types.DeriveSha(block.Transactions(), new(trie.Trie))
  57. if txnHash != block.Header().TxHash {
  58. return 0, istanbulcommon.ErrMismatchTxhashes
  59. }
  60. uncleHash := types.CalcUncleHash(block.Uncles())
  61. if uncleHash != nilUncleHash {
  62. return 0, istanbulcommon.ErrInvalidUncleHash
  63. }
  64. // verify the header of proposed block
  65. err := e.VerifyHeader(chain, block.Header(), nil, validators)
  66. if err == nil || err == istanbulcommon.ErrEmptyCommittedSeals {
  67. // ignore errEmptyCommittedSeals error because we don't have the committed seals yet
  68. return 0, nil
  69. } else if err == consensus.ErrFutureBlock {
  70. return time.Until(time.Unix(int64(block.Header().Time), 0)), consensus.ErrFutureBlock
  71. }
  72. return 0, err
  73. }
  74. func (e *Engine) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header, validators istanbul.ValidatorSet) error {
  75. return e.verifyHeader(chain, header, parents, validators)
  76. }
  77. // verifyHeader checks whether a header conforms to the consensus rules.The
  78. // caller may optionally pass in a batch of parents (ascending order) to avoid
  79. // looking those up from the database. This is useful for concurrently verifying
  80. // a batch of new headers.
  81. func (e *Engine) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header, validators istanbul.ValidatorSet) error {
  82. if header.Number == nil {
  83. return istanbulcommon.ErrUnknownBlock
  84. }
  85. // Don't waste time checking blocks from the future (adjusting for allowed threshold)
  86. adjustedTimeNow := time.Now().Add(time.Duration(e.cfg.AllowedFutureBlockTime) * time.Second).Unix()
  87. if header.Time > uint64(adjustedTimeNow) {
  88. return consensus.ErrFutureBlock
  89. }
  90. if _, err := types.ExtractIstanbulExtra(header); err != nil {
  91. return istanbulcommon.ErrInvalidExtraDataFormat
  92. }
  93. if header.Nonce != (istanbulcommon.EmptyBlockNonce) && !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) {
  94. return istanbulcommon.ErrInvalidNonce
  95. }
  96. // Ensure that the mix digest is zero as we don't have fork protection currently
  97. if header.MixDigest != types.IstanbulDigest {
  98. return istanbulcommon.ErrInvalidMixDigest
  99. }
  100. // Ensure that the block doesn't contain any uncles which are meaningless in Istanbul
  101. if header.UncleHash != nilUncleHash {
  102. return istanbulcommon.ErrInvalidUncleHash
  103. }
  104. // Ensure that the block's difficulty is meaningful (may not be correct at this point)
  105. if header.Difficulty == nil || header.Difficulty.Cmp(istanbulcommon.DefaultDifficulty) != 0 {
  106. return istanbulcommon.ErrInvalidDifficulty
  107. }
  108. return e.verifyCascadingFields(chain, header, validators, parents)
  109. }
  110. // verifyCascadingFields verifies all the header fields that are not standalone,
  111. // rather depend on a batch of previous headers. The caller may optionally pass
  112. // in a batch of parents (ascending order) to avoid looking those up from the
  113. // database. This is useful for concurrently verifying a batch of new headers.
  114. func (e *Engine) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, validators istanbul.ValidatorSet, parents []*types.Header) error {
  115. // The genesis block is the always valid dead-end
  116. number := header.Number.Uint64()
  117. if number == 0 {
  118. return nil
  119. }
  120. // Check parent
  121. var parent *types.Header
  122. if len(parents) > 0 {
  123. parent = parents[len(parents)-1]
  124. } else {
  125. parent = chain.GetHeader(header.ParentHash, number-1)
  126. }
  127. // Ensure that the block's parent has right number and hash
  128. if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
  129. return consensus.ErrUnknownAncestor
  130. }
  131. // Ensure that the block's timestamp isn't too close to it's parent
  132. if parent.Time+e.cfg.GetConfig(header.Number).BlockPeriod > header.Time {
  133. return istanbulcommon.ErrInvalidTimestamp
  134. }
  135. // Verify signer
  136. if err := e.verifySigner(chain, header, parents, validators); err != nil {
  137. return err
  138. }
  139. return e.verifyCommittedSeals(chain, header, parents, validators)
  140. }
  141. func (e *Engine) verifySigner(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header, validators istanbul.ValidatorSet) error {
  142. // Verifying the genesis block is not supported
  143. number := header.Number.Uint64()
  144. if number == 0 {
  145. return istanbulcommon.ErrUnknownBlock
  146. }
  147. // Resolve the authorization key and check against signers
  148. signer, err := e.Author(header)
  149. if err != nil {
  150. return err
  151. }
  152. // Signer should be in the validator set of previous block's extraData.
  153. if _, v := validators.GetByAddress(signer); v == nil {
  154. return istanbulcommon.ErrUnauthorized
  155. }
  156. return nil
  157. }
  158. // verifyCommittedSeals checks whether every committed seal is signed by one of the parent's validators
  159. func (e *Engine) verifyCommittedSeals(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header, validators istanbul.ValidatorSet) error {
  160. number := header.Number.Uint64()
  161. if number == 0 {
  162. // We don't need to verify committed seals in the genesis block
  163. return nil
  164. }
  165. extra, err := types.ExtractIstanbulExtra(header)
  166. if err != nil {
  167. return err
  168. }
  169. committedSeal := extra.CommittedSeal
  170. // The length of Committed seals should be larger than 0
  171. if len(committedSeal) == 0 {
  172. return istanbulcommon.ErrEmptyCommittedSeals
  173. }
  174. validatorsCpy := validators.Copy()
  175. // Check whether the committed seals are generated by validators
  176. validSeal := 0
  177. committers, err := e.Signers(header)
  178. if err != nil {
  179. return err
  180. }
  181. for _, addr := range committers {
  182. if validatorsCpy.RemoveValidator(addr) {
  183. validSeal++
  184. continue
  185. }
  186. return istanbulcommon.ErrInvalidCommittedSeals
  187. }
  188. // The length of validSeal should be larger than number of faulty node + 1
  189. if validSeal <= validators.F() {
  190. return istanbulcommon.ErrInvalidCommittedSeals
  191. }
  192. return nil
  193. }
  194. // VerifyUncles verifies that the given block's uncles conform to the consensus
  195. // rules of a given engine.
  196. func (e *Engine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
  197. if len(block.Uncles()) > 0 {
  198. return istanbulcommon.ErrInvalidUncleHash
  199. }
  200. return nil
  201. }
  202. // VerifySeal checks whether the crypto seal on a header is valid according to
  203. // the consensus rules of the given engine.
  204. func (e *Engine) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header, validators istanbul.ValidatorSet) error {
  205. // get parent header and ensure the signer is in parent's validator set
  206. number := header.Number.Uint64()
  207. if number == 0 {
  208. return istanbulcommon.ErrUnknownBlock
  209. }
  210. // ensure that the difficulty equals to istanbulcommon.DefaultDifficulty
  211. if header.Difficulty.Cmp(istanbulcommon.DefaultDifficulty) != 0 {
  212. return istanbulcommon.ErrInvalidDifficulty
  213. }
  214. return e.verifySigner(chain, header, nil, validators)
  215. }
  216. func (e *Engine) Prepare(chain consensus.ChainHeaderReader, header *types.Header, validators istanbul.ValidatorSet) error {
  217. header.Coinbase = common.Address{}
  218. header.Nonce = istanbulcommon.EmptyBlockNonce
  219. header.MixDigest = types.IstanbulDigest
  220. // copy the parent extra data as the header extra data
  221. number := header.Number.Uint64()
  222. parent := chain.GetHeader(header.ParentHash, number-1)
  223. if parent == nil {
  224. return consensus.ErrUnknownAncestor
  225. }
  226. // use the same difficulty for all blocks
  227. header.Difficulty = istanbulcommon.DefaultDifficulty
  228. // set header's timestamp
  229. header.Time = parent.Time + e.cfg.GetConfig(header.Number).BlockPeriod
  230. if header.Time < uint64(time.Now().Unix()) {
  231. header.Time = uint64(time.Now().Unix())
  232. }
  233. num := big.NewInt(0).SetUint64(number - 1)
  234. validatorContract := e.cfg.GetValidatorContractAddress(num)
  235. var addresses []common.Address
  236. if validatorContract != (common.Address{}) && e.cfg.GetValidatorSelectionMode(num) == params.ContractMode {
  237. addresses = []common.Address{}
  238. } else {
  239. // add validators in snapshot to extraData's validators section
  240. addresses = validator.SortedAddresses(validators.List())
  241. }
  242. extra, err := prepareExtra(header, addresses)
  243. if err != nil {
  244. return err
  245. }
  246. header.Extra = extra
  247. return nil
  248. }
  249. // Finalize runs any post-transaction state modifications (e.g. block rewards)
  250. // and assembles the final block.
  251. //
  252. // Note, the block header and state database might be updated to reflect any
  253. // consensus rules that happen at finalization (e.g. block rewards).
  254. func (e *Engine) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
  255. // No block rewards in Istanbul, so the state remains as is and uncles are dropped
  256. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
  257. header.UncleHash = nilUncleHash
  258. }
  259. // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
  260. // nor block rewards given, and returns the final block.
  261. func (e *Engine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
  262. /// No block rewards in Istanbul, so the state remains as is and uncles are dropped
  263. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
  264. header.UncleHash = nilUncleHash
  265. // Assemble and return the final block for sealing
  266. return types.NewBlock(header, txs, nil, receipts, new(trie.Trie)), nil
  267. }
  268. // Seal generates a new block for the given input block with the local miner's
  269. // seal place on top.
  270. func (e *Engine) Seal(chain consensus.ChainHeaderReader, block *types.Block, validators istanbul.ValidatorSet) (*types.Block, error) {
  271. // update the block header timestamp and signature and propose the block to core engine
  272. header := block.Header()
  273. number := header.Number.Uint64()
  274. if _, v := validators.GetByAddress(e.signer); v == nil {
  275. return block, istanbulcommon.ErrUnauthorized
  276. }
  277. parent := chain.GetHeader(header.ParentHash, number-1)
  278. if parent == nil {
  279. return block, consensus.ErrUnknownAncestor
  280. }
  281. return e.updateBlock(parent, block)
  282. }
  283. // update timestamp and signature of the block based on its number of transactions
  284. func (e *Engine) updateBlock(parent *types.Header, block *types.Block) (*types.Block, error) {
  285. // sign the hash
  286. header := block.Header()
  287. seal, err := e.sign(sigHash(header).Bytes())
  288. if err != nil {
  289. return nil, err
  290. }
  291. err = writeSeal(header, seal)
  292. if err != nil {
  293. return nil, err
  294. }
  295. return block.WithSeal(header), nil
  296. }
  297. // writeSeal writes the extra-data field of the given header with the given seals.
  298. // suggest to rename to writeSeal.
  299. func writeSeal(h *types.Header, seal []byte) error {
  300. if len(seal)%types.IstanbulExtraSeal != 0 {
  301. return istanbulcommon.ErrInvalidSignature
  302. }
  303. istanbulExtra, err := types.ExtractIstanbulExtra(h)
  304. if err != nil {
  305. return err
  306. }
  307. istanbulExtra.Seal = seal
  308. payload, err := rlp.EncodeToBytes(&istanbulExtra)
  309. if err != nil {
  310. return err
  311. }
  312. h.Extra = append(h.Extra[:types.IstanbulExtraVanity], payload...)
  313. return nil
  314. }
  315. func (e *Engine) SealHash(header *types.Header) common.Hash {
  316. return sigHash(header)
  317. }
  318. func (e *Engine) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
  319. return new(big.Int)
  320. }
  321. func (e *Engine) ExtractGenesisValidators(header *types.Header) ([]common.Address, error) {
  322. extra, err := types.ExtractIstanbulExtra(header)
  323. if err != nil {
  324. return nil, err
  325. }
  326. return extra.Validators, nil
  327. }
  328. func (e *Engine) Signers(header *types.Header) ([]common.Address, error) {
  329. extra, err := types.ExtractIstanbulExtra(header)
  330. if err != nil {
  331. return []common.Address{}, err
  332. }
  333. committedSeal := extra.CommittedSeal
  334. proposalSeal := PrepareCommittedSeal(header.Hash())
  335. var addrs []common.Address
  336. // 1. Get committed seals from current header
  337. for _, seal := range committedSeal {
  338. // 2. Get the original address by seal and parent block hash
  339. addr, err := istanbulcommon.GetSignatureAddress(proposalSeal, seal)
  340. if err != nil {
  341. return nil, istanbulcommon.ErrInvalidSignature
  342. }
  343. addrs = append(addrs, addr)
  344. }
  345. return addrs, nil
  346. }
  347. func (e *Engine) Address() common.Address {
  348. return e.signer
  349. }
  350. func (e *Engine) WriteVote(header *types.Header, candidate common.Address, authorize bool) error {
  351. header.Coinbase = candidate
  352. if authorize {
  353. copy(header.Nonce[:], nonceAuthVote)
  354. } else {
  355. copy(header.Nonce[:], nonceDropVote)
  356. }
  357. return nil
  358. }
  359. func (e *Engine) ReadVote(header *types.Header) (candidate common.Address, authorize bool, err error) {
  360. switch {
  361. case bytes.Equal(header.Nonce[:], nonceAuthVote):
  362. authorize = true
  363. case bytes.Equal(header.Nonce[:], nonceDropVote):
  364. authorize = false
  365. default:
  366. return common.Address{}, false, istanbulcommon.ErrInvalidVote
  367. }
  368. return header.Coinbase, authorize, nil
  369. }
  370. // FIXME: Need to update this for Istanbul
  371. // sigHash returns the hash which is used as input for the Istanbul
  372. // signing. It is the hash of the entire header apart from the 65 byte signature
  373. // contained at the end of the extra data.
  374. //
  375. // Note, the method requires the extra data to be at least 65 bytes, otherwise it
  376. // panics. This is done to avoid accidentally using both forms (signature present
  377. // or not), which could be abused to produce different hashes for the same header.
  378. func sigHash(header *types.Header) (hash common.Hash) {
  379. hasher := sha3.NewLegacyKeccak256()
  380. rlp.Encode(hasher, types.IstanbulFilteredHeader(header, false))
  381. hasher.Sum(hash[:0])
  382. return hash
  383. }
  384. // prepareExtra returns a extra-data of the given header and validators
  385. func prepareExtra(header *types.Header, vals []common.Address) ([]byte, error) {
  386. var buf bytes.Buffer
  387. // compensate the lack bytes if header.Extra is not enough IstanbulExtraVanity bytes.
  388. if len(header.Extra) < types.IstanbulExtraVanity {
  389. header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity-len(header.Extra))...)
  390. }
  391. buf.Write(header.Extra[:types.IstanbulExtraVanity])
  392. ist := &types.IstanbulExtra{
  393. Validators: vals,
  394. Seal: []byte{},
  395. CommittedSeal: [][]byte{},
  396. }
  397. payload, err := rlp.EncodeToBytes(&ist)
  398. if err != nil {
  399. return nil, err
  400. }
  401. return append(buf.Bytes(), payload...), nil
  402. }
  403. func writeCommittedSeals(h *types.Header, committedSeals [][]byte) error {
  404. if len(committedSeals) == 0 {
  405. return istanbulcommon.ErrInvalidCommittedSeals
  406. }
  407. for _, seal := range committedSeals {
  408. if len(seal) != types.IstanbulExtraSeal {
  409. return istanbulcommon.ErrInvalidCommittedSeals
  410. }
  411. }
  412. istanbulExtra, err := types.ExtractIstanbulExtra(h)
  413. if err != nil {
  414. return err
  415. }
  416. istanbulExtra.CommittedSeal = make([][]byte, len(committedSeals))
  417. copy(istanbulExtra.CommittedSeal, committedSeals)
  418. payload, err := rlp.EncodeToBytes(&istanbulExtra)
  419. if err != nil {
  420. return err
  421. }
  422. h.Extra = append(h.Extra[:types.IstanbulExtraVanity], payload...)
  423. return nil
  424. }
  425. // PrepareCommittedSeal returns a committed seal for the given hash
  426. func PrepareCommittedSeal(hash common.Hash) []byte {
  427. var buf bytes.Buffer
  428. buf.Write(hash.Bytes())
  429. buf.Write([]byte{byte(ibfttypes.MsgCommit)})
  430. return buf.Bytes()
  431. }