github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/genesis.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:35</date> 10 //</624450078836264960> 11 12 13 package core 14 15 import ( 16 "bytes" 17 "encoding/hex" 18 "encoding/json" 19 "errors" 20 "fmt" 21 "math/big" 22 "strings" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/common/hexutil" 26 "github.com/ethereum/go-ethereum/common/math" 27 "github.com/ethereum/go-ethereum/core/rawdb" 28 "github.com/ethereum/go-ethereum/core/state" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/ethdb" 31 "github.com/ethereum/go-ethereum/log" 32 "github.com/ethereum/go-ethereum/params" 33 "github.com/ethereum/go-ethereum/rlp" 34 ) 35 36 //go:生成gencodec-类型genesis-场覆盖genesspecmarshaling-out gen_genesis.go 37 //go:generate gencodec-type genesiaccount-field override genesiaccountmarshaling-out gen_genesis_account.go 38 39 var errGenesisNoConfig = errors.New("genesis has no chain configuration") 40 41 //Genesis指定头字段,Genesis块的状态。它也很难定义 42 //拨叉转换块通过链条配置。 43 type Genesis struct { 44 Config *params.ChainConfig `json:"config"` 45 Nonce uint64 `json:"nonce"` 46 Timestamp uint64 `json:"timestamp"` 47 ExtraData []byte `json:"extraData"` 48 GasLimit uint64 `json:"gasLimit" gencodec:"required"` 49 Difficulty *big.Int `json:"difficulty" gencodec:"required"` 50 Mixhash common.Hash `json:"mixHash"` 51 Coinbase common.Address `json:"coinbase"` 52 Alloc GenesisAlloc `json:"alloc" gencodec:"required"` 53 54 //这些字段用于一致性测试。请不要用它们 55 //在真正的创世纪块体中。 56 Number uint64 `json:"number"` 57 GasUsed uint64 `json:"gasUsed"` 58 ParentHash common.Hash `json:"parentHash"` 59 } 60 61 //genesisalloc指定作为Genesis块一部分的初始状态。 62 type GenesisAlloc map[common.Address]GenesisAccount 63 64 func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { 65 m := make(map[common.UnprefixedAddress]GenesisAccount) 66 if err := json.Unmarshal(data, &m); err != nil { 67 return err 68 } 69 *ga = make(GenesisAlloc) 70 for addr, a := range m { 71 (*ga)[common.Address(addr)] = a 72 } 73 return nil 74 } 75 76 //Genesiaccount是一个处于Genesis区块状态的账户。 77 type GenesisAccount struct { 78 Code []byte `json:"code,omitempty"` 79 Storage map[common.Hash]common.Hash `json:"storage,omitempty"` 80 Balance *big.Int `json:"balance" gencodec:"required"` 81 Nonce uint64 `json:"nonce,omitempty"` 82 PrivateKey []byte `json:"secretKey,omitempty"` //为了测试 83 } 84 85 //gencodec的字段类型重写 86 type genesisSpecMarshaling struct { 87 Nonce math.HexOrDecimal64 88 Timestamp math.HexOrDecimal64 89 ExtraData hexutil.Bytes 90 GasLimit math.HexOrDecimal64 91 GasUsed math.HexOrDecimal64 92 Number math.HexOrDecimal64 93 Difficulty *math.HexOrDecimal256 94 Alloc map[common.UnprefixedAddress]GenesisAccount 95 } 96 97 type genesisAccountMarshaling struct { 98 Code hexutil.Bytes 99 Balance *math.HexOrDecimal256 100 Nonce math.HexOrDecimal64 101 Storage map[storageJSON]storageJSON 102 PrivateKey hexutil.Bytes 103 } 104 105 //storagejson表示一个256位字节数组,但当 106 //从十六进制解组。 107 type storageJSON common.Hash 108 109 func (h *storageJSON) UnmarshalText(text []byte) error { 110 text = bytes.TrimPrefix(text, []byte("0x")) 111 if len(text) > 64 { 112 return fmt.Errorf("too many hex characters in storage key/value %q", text) 113 } 114 offset := len(h) - len(text)/2 //左边的垫子 115 if _, err := hex.Decode(h[offset:], text); err != nil { 116 fmt.Println(err) 117 return fmt.Errorf("invalid hex storage key/value %q", text) 118 } 119 return nil 120 } 121 122 func (h storageJSON) MarshalText() ([]byte, error) { 123 return hexutil.Bytes(h[:]).MarshalText() 124 } 125 126 //尝试覆盖现有的 127 //与不相容的起源块。 128 type GenesisMismatchError struct { 129 Stored, New common.Hash 130 } 131 132 func (e *GenesisMismatchError) Error() string { 133 return fmt.Sprintf("database already contains an incompatible genesis block (have %x, new %x)", e.Stored[:8], e.New[:8]) 134 } 135 136 //SetupGenesBlock在数据库中写入或更新Genesis块。 137 //将要使用的块是: 138 // 139 //创世纪=零创世纪!=零 140 //+————————————————————————————————————— 141 //DB没有Genesis主网络默认Genesis 142 //DB有来自DB的Genesis(如果兼容) 143 // 144 //如果存储链配置兼容(即不兼容),则将更新该配置 145 //在本地头块下面指定一个叉块)。如果发生冲突, 146 //错误是一个*params.configcompaterror,并返回新的未写入配置。 147 // 148 //The returned chain configuration is never nil. 149 func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { 150 return SetupGenesisBlockWithOverride(db, genesis, nil) 151 } 152 func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, constantinopleOverride *big.Int) (*params.ChainConfig, common.Hash, error) { 153 if genesis != nil && genesis.Config == nil { 154 return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig 155 } 156 157 //如果没有存储的Genesis块,只需提交新块。 158 stored := rawdb.ReadCanonicalHash(db, 0) 159 if (stored == common.Hash{}) { 160 if genesis == nil { 161 log.Info("Writing default main-net genesis block") 162 genesis = DefaultGenesisBlock() 163 } else { 164 log.Info("Writing custom genesis block") 165 } 166 block, err := genesis.Commit(db) 167 return genesis.Config, block.Hash(), err 168 } 169 170 //检查Genesis块是否已经写入。 171 if genesis != nil { 172 hash := genesis.ToBlock(nil).Hash() 173 if hash != stored { 174 return genesis.Config, hash, &GenesisMismatchError{stored, hash} 175 } 176 } 177 178 //获取现有的链配置。 179 newcfg := genesis.configOrDefault(stored) 180 if constantinopleOverride != nil { 181 newcfg.ConstantinopleBlock = constantinopleOverride 182 } 183 storedcfg := rawdb.ReadChainConfig(db, stored) 184 if storedcfg == nil { 185 log.Warn("Found genesis block without chain config") 186 rawdb.WriteChainConfig(db, stored, newcfg) 187 return newcfg, stored, nil 188 } 189 //特殊情况:如果没有新的,不要更改非主网链的现有配置 190 //提供了配置。这些链将得到所有的协议更改(以及compat错误) 191 //如果我们继续的话。 192 if genesis == nil && stored != params.MainnetGenesisHash { 193 return storedcfg, stored, nil 194 } 195 196 //检查配置兼容性并写入配置。兼容性错误 197 //除非我们已经在零区,否则将返回给调用方。 198 height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db)) 199 if height == nil { 200 return newcfg, stored, fmt.Errorf("missing block number for head header hash") 201 } 202 compatErr := storedcfg.CheckCompatible(newcfg, *height) 203 if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 { 204 return newcfg, stored, compatErr 205 } 206 rawdb.WriteChainConfig(db, stored, newcfg) 207 return newcfg, stored, nil 208 } 209 210 func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { 211 switch { 212 case g != nil: 213 return g.Config 214 case ghash == params.MainnetGenesisHash: 215 return params.MainnetChainConfig 216 case ghash == params.TestnetGenesisHash: 217 return params.TestnetChainConfig 218 default: 219 return params.AllEthashProtocolChanges 220 } 221 } 222 223 //toblock创建genesis块并写入genesis规范的状态 224 //到给定的数据库(如果没有则丢弃它)。 225 func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { 226 if db == nil { 227 db = ethdb.NewMemDatabase() 228 } 229 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 230 for addr, account := range g.Alloc { 231 statedb.AddBalance(addr, account.Balance) 232 statedb.SetCode(addr, account.Code) 233 statedb.SetNonce(addr, account.Nonce) 234 for key, value := range account.Storage { 235 statedb.SetState(addr, key, value) 236 } 237 } 238 root := statedb.IntermediateRoot(false) 239 head := &types.Header{ 240 Number: new(big.Int).SetUint64(g.Number), 241 Nonce: types.EncodeNonce(g.Nonce), 242 Time: new(big.Int).SetUint64(g.Timestamp), 243 ParentHash: g.ParentHash, 244 Extra: g.ExtraData, 245 GasLimit: g.GasLimit, 246 GasUsed: g.GasUsed, 247 Difficulty: g.Difficulty, 248 MixDigest: g.Mixhash, 249 Coinbase: g.Coinbase, 250 Root: root, 251 } 252 if g.GasLimit == 0 { 253 head.GasLimit = params.GenesisGasLimit 254 } 255 if g.Difficulty == nil { 256 head.Difficulty = params.GenesisDifficulty 257 } 258 statedb.Commit(false) 259 statedb.Database().TrieDB().Commit(root, true) 260 261 return types.NewBlock(head, nil, nil, nil) 262 } 263 264 //commit将Genesis规范的块和状态写入数据库。 265 //该块作为规范头块提交。 266 func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { 267 block := g.ToBlock(db) 268 if block.Number().Sign() != 0 { 269 return nil, fmt.Errorf("can't commit genesis block with number > 0") 270 } 271 rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty) 272 rawdb.WriteBlock(db, block) 273 rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) 274 rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) 275 rawdb.WriteHeadBlockHash(db, block.Hash()) 276 rawdb.WriteHeadHeaderHash(db, block.Hash()) 277 278 config := g.Config 279 if config == nil { 280 config = params.AllEthashProtocolChanges 281 } 282 rawdb.WriteChainConfig(db, block.Hash(), config) 283 return block, nil 284 } 285 286 //mustcommit将genesis块和状态写入db,并在出错时惊慌失措。 287 //该块作为规范头块提交。 288 func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { 289 block, err := g.Commit(db) 290 if err != nil { 291 panic(err) 292 } 293 return block 294 } 295 296 //genesisblockfortesting创建并写入一个块,其中addr具有给定的wei平衡。 297 func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { 298 g := Genesis{Alloc: GenesisAlloc{addr: {Balance: balance}}} 299 return g.MustCommit(db) 300 } 301 302 //defaultgenesisblock返回以太坊主网Genesis块。 303 func DefaultGenesisBlock() *Genesis { 304 return &Genesis{ 305 Config: params.MainnetChainConfig, 306 Nonce: 66, 307 ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"), 308 GasLimit: 5000, 309 Difficulty: big.NewInt(17179869184), 310 Alloc: decodePrealloc(mainnetAllocData), 311 } 312 } 313 314 //DefaultTestNetGenesBlock返回Ropsten Network Genesis块。 315 func DefaultTestnetGenesisBlock() *Genesis { 316 return &Genesis{ 317 Config: params.TestnetChainConfig, 318 Nonce: 66, 319 ExtraData: hexutil.MustDecode("0x3535353535353535353535353535353535353535353535353535353535353535"), 320 GasLimit: 16777216, 321 Difficulty: big.NewInt(1048576), 322 Alloc: decodePrealloc(testnetAllocData), 323 } 324 } 325 326 //defaultrinkebygenesblock返回rinkeby网络genesis块。 327 func DefaultRinkebyGenesisBlock() *Genesis { 328 return &Genesis{ 329 Config: params.RinkebyChainConfig, 330 Timestamp: 1492009146, 331 ExtraData: hexutil.MustDecode("0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), 332 GasLimit: 4700000, 333 Difficulty: big.NewInt(1), 334 Alloc: decodePrealloc(rinkebyAllocData), 335 } 336 } 337 338 //developergenessblock返回“geth--dev”genesis块。注意,这必须 339 //播种 340 func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis { 341 //将默认期间覆盖到用户请求的期间 342 config := *params.AllCliqueProtocolChanges 343 config.Clique.Period = period 344 345 //组装并返回带有预编译和水龙头的Genesis 346 return &Genesis{ 347 Config: &config, 348 ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...), 349 GasLimit: 6283185, 350 Difficulty: big.NewInt(1), 351 Alloc: map[common.Address]GenesisAccount{ 352 common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, //恢复正常 353 common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, //沙256 354 common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, //里米德 355 common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, //身份 356 common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, //莫德斯普 357 common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, //埃卡德 358 common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, //蜕皮素 359 common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, //蜕变 360 faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, 361 }, 362 } 363 } 364 365 func decodePrealloc(data string) GenesisAlloc { 366 var p []struct{ Addr, Balance *big.Int } 367 if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil { 368 panic(err) 369 } 370 ga := make(GenesisAlloc, len(p)) 371 for _, account := range p { 372 ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance} 373 } 374 return ga 375 } 376