github.com/igggame/nebulas-go@v2.1.0+incompatible/core/genesis.go (about) 1 // Copyright (C) 2017 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package core 20 21 import ( 22 "fmt" 23 "io/ioutil" 24 25 "github.com/nebulasio/go-nebulas/crypto/keystore" 26 27 "github.com/gogo/protobuf/proto" 28 "github.com/nebulasio/go-nebulas/common/dag" 29 "github.com/nebulasio/go-nebulas/consensus/pb" 30 "github.com/nebulasio/go-nebulas/core/pb" 31 "github.com/nebulasio/go-nebulas/core/state" 32 "github.com/nebulasio/go-nebulas/util" 33 "github.com/nebulasio/go-nebulas/util/logging" 34 "github.com/sirupsen/logrus" 35 ) 36 37 // Genesis Block Hash 38 var ( 39 GenesisHash = make([]byte, BlockHashLength) 40 GenesisTimestamp = int64(0) 41 GenesisCoinbase, _ = NewAddressFromPublicKey(make([]byte, PublicKeyDataLength)) 42 ) 43 44 // LoadGenesisConf load genesis conf for file 45 func LoadGenesisConf(filePath string) (*corepb.Genesis, error) { 46 b, err := ioutil.ReadFile(filePath) 47 if err != nil { 48 logging.CLog().WithFields(logrus.Fields{ 49 "err": err, 50 }).Error("Failed to read the genesis config file.") 51 return nil, err 52 } 53 content := string(b) 54 55 genesis := new(corepb.Genesis) 56 if err := proto.UnmarshalText(content, genesis); err != nil { 57 logging.CLog().WithFields(logrus.Fields{ 58 "err": err, 59 }).Error("Failed to parse genesis file.") 60 return nil, err 61 } 62 63 return genesis, nil 64 } 65 66 // NewGenesisBlock create genesis @Block from file. 67 func NewGenesisBlock(conf *corepb.Genesis, chain *BlockChain) (*Block, error) { 68 if conf == nil || chain == nil { 69 return nil, ErrNilArgument 70 } 71 72 worldState, err := state.NewWorldState(chain.ConsensusHandler(), chain.storage) 73 if err != nil { 74 return nil, err 75 } 76 genesisBlock := &Block{ 77 header: &BlockHeader{ 78 hash: GenesisHash, 79 parentHash: GenesisHash, 80 chainID: conf.Meta.ChainId, 81 coinbase: GenesisCoinbase, 82 timestamp: GenesisTimestamp, 83 consensusRoot: &consensuspb.ConsensusRoot{}, 84 alg: keystore.SECP256K1, 85 }, 86 transactions: make(Transactions, 0), 87 dependency: dag.NewDag(), 88 worldState: worldState, 89 txPool: chain.txPool, 90 storage: chain.storage, 91 eventEmitter: chain.eventEmitter, 92 nvm: chain.nvm, 93 dip: chain.dip, 94 height: 1, 95 sealed: false, 96 } 97 98 consensusState, err := chain.ConsensusHandler().GenesisConsensusState(chain, conf) 99 if err != nil { 100 return nil, err 101 } 102 genesisBlock.worldState.SetConsensusState(consensusState) 103 104 if err := genesisBlock.Begin(); err != nil { 105 return nil, err 106 } 107 // add token distribution for genesis 108 for _, v := range conf.TokenDistribution { 109 addr, err := AddressParse(v.Address) 110 if err != nil { 111 logging.CLog().WithFields(logrus.Fields{ 112 "address": v.Address, 113 "err": err, 114 }).Error("Found invalid address in genesis token distribution.") 115 genesisBlock.RollBack() 116 return nil, err 117 } 118 acc, err := genesisBlock.worldState.GetOrCreateUserAccount(addr.address) 119 if err != nil { 120 genesisBlock.RollBack() 121 return nil, err 122 } 123 txsBalance, err := util.NewUint128FromString(v.Value) 124 if err != nil { 125 genesisBlock.RollBack() 126 return nil, err 127 } 128 err = acc.AddBalance(txsBalance) 129 if err != nil { 130 genesisBlock.RollBack() 131 return nil, err 132 } 133 } 134 135 // genesis transaction 136 declaration := fmt.Sprintf( 137 "%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n\n\n%s", 138 "Nebulas Manifesto", 139 "Yes! We Believe", 140 "We believe blockchains are a foundational innovation of the new world. At its essence, this innovation is about the decentralization of data. People will be empowered to claim ownership of their data through tokens, which will enable data to be valued and exchanged by everyone on the blockchain.", 141 "The blockchain community embodies the values of openness, collaboration, and transparency. An ecosystem created by blockchain believers is a voluntary association anchored by aligned incentives. We believe blockchain represents the social contract of the future, and that will lead to a civilization where cooperation, inclusion, and the interests of society converge.", 142 "Blockchains will make life more free, equitable and purposeful. As a nascent digital organism and economic system, blockchain is fertile ground for creative evolution. It will give rise to transformative ideas and breakthrough technologies. Now is a time of great opportunity, challenge and hope.", 143 "Do not ask what blockchain can do for you. Ask what you can do for blockchain.", 144 "This is the genesis of Nebulas.", 145 146 "星云宣言", 147 "Yes! We Believe", 148 "我们认为,区块链是奠基新世界的颠覆式创新,其本质是去中心化的数据确权。确权的数据承载于通证之上,对于“链上”数据的交互具有不可或缺的作用。", 149 "我们同时看到,真正的区块链社区秉持着开放、共享、透明的精神,逐步建立人类历史上前所未有的大规模协作关系。一个公正并有效的价值发现、激励以及持续进化机制所构成的生态系统,是这场大规模协作关系蓬勃发展的原生推动力,也是星云对于区块链的伟大使命。", 150 "我们始终坚信,区块链技术会帮助人们抵达更为自由、平等、美好的生活。区块链作为全新的生命体和经济体,意味着新的思想和技术,也蕴含着新的挑战、机遇和希望。面对无穷可能性的感召,不要问区块链能为你做什么,要问你能为区块链做什么。", 151 "星云正是为此而生。", 152 153 "by Nebulas (nebulas.io)", 154 ) 155 declarationTx, err := NewTransaction( 156 chain.ChainID(), 157 GenesisCoinbase, GenesisCoinbase, 158 util.Uint128Zero(), 1, 159 TxPayloadBinaryType, 160 []byte(declaration), 161 GenesisGasPrice, 162 MinGasCountPerTransaction, 163 ) 164 if err != nil { 165 return nil, err 166 } 167 declarationTx.timestamp = 0 168 hash, err := declarationTx.calHash() 169 if err != nil { 170 return nil, err 171 } 172 declarationTx.hash = hash 173 declarationTx.alg = keystore.SECP256K1 174 pbTx, err := declarationTx.ToProto() 175 if err != nil { 176 return nil, err 177 } 178 txBytes, err := proto.Marshal(pbTx) 179 if err != nil { 180 return nil, err 181 } 182 genesisBlock.transactions = append(genesisBlock.transactions, declarationTx) 183 if err := genesisBlock.worldState.PutTx(declarationTx.hash, txBytes); err != nil { 184 return nil, err 185 } 186 187 genesisBlock.Commit() 188 189 genesisBlock.header.stateRoot = genesisBlock.WorldState().AccountsRoot() 190 genesisBlock.header.txsRoot = genesisBlock.WorldState().TxsRoot() 191 genesisBlock.header.eventsRoot = genesisBlock.WorldState().EventsRoot() 192 genesisBlock.header.consensusRoot = genesisBlock.WorldState().ConsensusRoot() 193 194 genesisBlock.sealed = true 195 196 return genesisBlock, nil 197 } 198 199 // CheckGenesisBlock if a block is a genesis block 200 func CheckGenesisBlock(block *Block) bool { 201 if block == nil { 202 return false 203 } 204 if block.Hash().Equals(GenesisHash) { 205 return true 206 } 207 return false 208 } 209 210 // CheckGenesisTransaction if a tx is a genesis transaction 211 func CheckGenesisTransaction(tx *Transaction) bool { 212 if tx == nil { 213 return false 214 } 215 if tx.from.Equals(GenesisCoinbase) { 216 return true 217 } 218 return false 219 } 220 221 // DumpGenesis return the configuration of the genesis block in the storage 222 func DumpGenesis(chain *BlockChain) (*corepb.Genesis, error) { 223 genesis, err := LoadBlockFromStorage(GenesisHash, chain) 224 if err != nil { 225 return nil, err 226 } 227 dynasty, err := genesis.worldState.Dynasty() 228 if err != nil { 229 return nil, err 230 } 231 bootstrap := []string{} 232 for _, v := range dynasty { 233 addr, err := AddressParseFromBytes(v) 234 if err != nil { 235 return nil, err 236 } 237 bootstrap = append(bootstrap, addr.String()) 238 } 239 distribution := []*corepb.GenesisTokenDistribution{} 240 accounts, err := genesis.worldState.Accounts() 241 if err != nil { 242 return nil, err 243 } 244 for _, v := range accounts { 245 balance := v.Balance() 246 if v.Address().Equals(genesis.Coinbase().Bytes()) { 247 continue 248 } 249 addr, err := AddressParseFromBytes(v.Address()) 250 if err != nil { 251 return nil, err 252 } 253 distribution = append(distribution, &corepb.GenesisTokenDistribution{ 254 Address: addr.String(), 255 Value: balance.String(), 256 }) 257 } 258 return &corepb.Genesis{ 259 Meta: &corepb.GenesisMeta{ChainId: genesis.ChainID()}, 260 Consensus: &corepb.GenesisConsensus{ 261 Dpos: &corepb.GenesisConsensusDpos{Dynasty: bootstrap}, 262 }, 263 TokenDistribution: distribution, 264 }, nil 265 } 266 267 //CheckGenesisConfByDB check mem and genesis.conf if equal return nil 268 func CheckGenesisConfByDB(pGenesisDB *corepb.Genesis, pGenesis *corepb.Genesis) error { 269 //private function [Empty parameters are checked by the caller] 270 if pGenesisDB != nil { 271 if pGenesis.Meta.ChainId != pGenesisDB.Meta.ChainId { 272 return ErrGenesisNotEqualChainIDInDB 273 } 274 275 if len(pGenesis.Consensus.Dpos.Dynasty) != len(pGenesisDB.Consensus.Dpos.Dynasty) { 276 return ErrGenesisNotEqualDynastyLenInDB 277 } 278 279 if len(pGenesis.TokenDistribution) != len(pGenesisDB.TokenDistribution) { 280 return ErrGenesisNotEqualTokenLenInDB 281 } 282 283 // check dpos equal 284 for _, confDposAddr := range pGenesis.Consensus.Dpos.Dynasty { 285 contains := false 286 for _, dposAddr := range pGenesisDB.Consensus.Dpos.Dynasty { 287 if dposAddr == confDposAddr { 288 contains = true 289 break 290 } 291 } 292 if !contains { 293 return ErrGenesisNotEqualDynastyInDB 294 } 295 296 } 297 298 // check distribution equal 299 for _, confDistribution := range pGenesis.TokenDistribution { 300 contains := false 301 for _, distribution := range pGenesisDB.TokenDistribution { 302 if distribution.Address == confDistribution.Address && 303 distribution.Value == confDistribution.Value { 304 contains = true 305 break 306 } 307 } 308 if !contains { 309 return ErrGenesisNotEqualTokenInDB 310 } 311 } 312 } 313 return nil 314 }