genesis_test.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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 core
  17. import (
  18. "math/big"
  19. "reflect"
  20. "testing"
  21. "github.com/davecgh/go-spew/spew"
  22. "github.com/ethereum/go-ethereum/common"
  23. "github.com/ethereum/go-ethereum/consensus/ethash"
  24. "github.com/ethereum/go-ethereum/core/rawdb"
  25. "github.com/ethereum/go-ethereum/core/vm"
  26. "github.com/ethereum/go-ethereum/ethdb"
  27. "github.com/ethereum/go-ethereum/params"
  28. )
  29. func TestInvalidCliqueConfig(t *testing.T) {
  30. block := DefaultGoerliGenesisBlock()
  31. block.ExtraData = []byte{}
  32. if _, err := block.Commit(nil); err == nil {
  33. t.Fatal("Expected error on invalid clique config")
  34. }
  35. }
  36. func TestSetupGenesis(t *testing.T) {
  37. var (
  38. customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
  39. customg = Genesis{
  40. Config: &params.ChainConfig{HomesteadBlock: big.NewInt(3)},
  41. Alloc: GenesisAlloc{
  42. {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
  43. },
  44. }
  45. oldcustomg = customg
  46. )
  47. oldcustomg.Config = &params.ChainConfig{HomesteadBlock: big.NewInt(2)}
  48. tests := []struct {
  49. name string
  50. fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error)
  51. wantConfig *params.ChainConfig
  52. wantHash common.Hash
  53. wantErr error
  54. }{
  55. {
  56. name: "genesis without ChainConfig",
  57. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  58. return SetupGenesisBlock(db, new(Genesis))
  59. },
  60. wantErr: errGenesisNoConfig,
  61. wantConfig: params.AllEthashProtocolChanges,
  62. },
  63. {
  64. name: "no block in DB, genesis == nil",
  65. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  66. return SetupGenesisBlock(db, nil)
  67. },
  68. wantHash: params.MainnetGenesisHash,
  69. wantConfig: params.MainnetChainConfig,
  70. },
  71. {
  72. name: "mainnet block in DB, genesis == nil",
  73. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  74. DefaultGenesisBlock().MustCommit(db)
  75. return SetupGenesisBlock(db, nil)
  76. },
  77. wantHash: params.MainnetGenesisHash,
  78. wantConfig: params.MainnetChainConfig,
  79. },
  80. {
  81. name: "custom block in DB, genesis == nil",
  82. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  83. customg.MustCommit(db)
  84. return SetupGenesisBlock(db, nil)
  85. },
  86. wantHash: customghash,
  87. wantConfig: customg.Config,
  88. },
  89. {
  90. name: "custom block in DB, genesis == ropsten",
  91. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  92. customg.MustCommit(db)
  93. return SetupGenesisBlock(db, DefaultRopstenGenesisBlock())
  94. },
  95. wantErr: &GenesisMismatchError{Stored: customghash, New: params.RopstenGenesisHash},
  96. wantHash: params.RopstenGenesisHash,
  97. wantConfig: params.RopstenChainConfig,
  98. },
  99. {
  100. name: "compatible config in DB",
  101. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  102. oldcustomg.MustCommit(db)
  103. return SetupGenesisBlock(db, &customg)
  104. },
  105. wantHash: customghash,
  106. wantConfig: customg.Config,
  107. },
  108. {
  109. name: "incompatible config in DB",
  110. fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
  111. // Commit the 'old' genesis block with Homestead transition at #2.
  112. // Advance to block #4, past the homestead transition block of customg.
  113. genesis := oldcustomg.MustCommit(db)
  114. bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil, nil)
  115. defer bc.Stop()
  116. blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
  117. bc.InsertChain(blocks)
  118. bc.CurrentBlock()
  119. // This should return a compatibility error.
  120. return SetupGenesisBlock(db, &customg)
  121. },
  122. wantHash: customghash,
  123. wantConfig: customg.Config,
  124. wantErr: &params.ConfigCompatError{
  125. What: "Homestead fork block",
  126. StoredConfig: big.NewInt(2),
  127. NewConfig: big.NewInt(3),
  128. RewindTo: 1,
  129. },
  130. },
  131. }
  132. for _, test := range tests {
  133. db := rawdb.NewMemoryDatabase()
  134. config, hash, err := test.fn(db)
  135. // Check the return values.
  136. if !reflect.DeepEqual(err, test.wantErr) {
  137. spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
  138. t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
  139. }
  140. if !reflect.DeepEqual(config, test.wantConfig) {
  141. t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig)
  142. }
  143. if hash != test.wantHash {
  144. t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
  145. } else if err == nil {
  146. // Check database content.
  147. stored := rawdb.ReadBlock(db, test.wantHash, 0)
  148. if stored.Hash() != test.wantHash {
  149. t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
  150. }
  151. }
  152. }
  153. }
  154. // TestGenesisHashes checks the congruity of default genesis data to
  155. // corresponding hardcoded genesis hash values.
  156. func TestGenesisHashes(t *testing.T) {
  157. for i, c := range []struct {
  158. genesis *Genesis
  159. want common.Hash
  160. }{
  161. {DefaultGenesisBlock(), params.MainnetGenesisHash},
  162. {DefaultGoerliGenesisBlock(), params.GoerliGenesisHash},
  163. {DefaultRopstenGenesisBlock(), params.RopstenGenesisHash},
  164. {DefaultRinkebyGenesisBlock(), params.RinkebyGenesisHash},
  165. {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
  166. } {
  167. // Test via MustCommit
  168. if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want {
  169. t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
  170. }
  171. // Test via ToBlock
  172. if have := c.genesis.ToBlock().Hash(); have != c.want {
  173. t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
  174. }
  175. }
  176. }
  177. func TestGenesis_Commit(t *testing.T) {
  178. genesis := &Genesis{
  179. BaseFee: big.NewInt(params.InitialBaseFee),
  180. Config: params.TestChainConfig,
  181. // difficulty is nil
  182. }
  183. db := rawdb.NewMemoryDatabase()
  184. genesisBlock := genesis.MustCommit(db)
  185. if genesis.Difficulty != nil {
  186. t.Fatalf("assumption wrong")
  187. }
  188. // This value should have been set as default in the ToBlock method.
  189. if genesisBlock.Difficulty().Cmp(params.GenesisDifficulty) != 0 {
  190. t.Errorf("assumption wrong: want: %d, got: %v", params.GenesisDifficulty, genesisBlock.Difficulty())
  191. }
  192. // Expect the stored total difficulty to be the difficulty of the genesis block.
  193. stored := rawdb.ReadTd(db, genesisBlock.Hash(), genesisBlock.NumberU64())
  194. if stored.Cmp(genesisBlock.Difficulty()) != 0 {
  195. t.Errorf("inequal difficulty; stored: %v, genesisBlock: %v", stored, genesisBlock.Difficulty())
  196. }
  197. }
  198. func TestReadWriteGenesisAlloc(t *testing.T) {
  199. var (
  200. db = rawdb.NewMemoryDatabase()
  201. alloc = &GenesisAlloc{
  202. {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
  203. {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
  204. }
  205. hash, _ = alloc.deriveHash()
  206. )
  207. alloc.flush(db)
  208. var reload GenesisAlloc
  209. err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash))
  210. if err != nil {
  211. t.Fatalf("Failed to load genesis state %v", err)
  212. }
  213. if len(reload) != len(*alloc) {
  214. t.Fatal("Unexpected genesis allocation")
  215. }
  216. for addr, account := range reload {
  217. want, ok := (*alloc)[addr]
  218. if !ok {
  219. t.Fatal("Account is not found")
  220. }
  221. if !reflect.DeepEqual(want, account) {
  222. t.Fatal("Unexpected account")
  223. }
  224. }
  225. }