// GenerateChain creates a chain of n blocks. The first block's // parent will be the provided parent. db is used to store // intermediate states and should contain the parent's state trie. // // The generator function is called with a new block generator for // every block. Any transactions and uncles added to the generator // become part of the block. If gen is nil, the blocks will be empty // and their coinbase will be the zero address. // // Blocks created by GenerateChain do not contain valid proof of work // values. Inserting them into BlockChain requires use of FakePow or // a similar non-validating proof of work implementation. func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { statedb, err := state.New(parent.Root(), db) if err != nil { panic(err) } blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) genblock := func(i int, h *types.Header) (*types.Block, types.Receipts) { b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb} if gen != nil { gen(i, b) } AccumulateRewards(statedb, h, b.uncles) root, err := statedb.Commit() if err != nil { panic(fmt.Sprintf("state write error: %v", err)) } h.Root = root return types.NewBlock(h, b.txs, b.uncles, b.receipts), b.receipts } for i := 0; i < n; i++ { header := makeHeader(parent, statedb) block, receipt := genblock(i, header) blocks[i] = block receipts[i] = receipt parent = block } return blocks, receipts }
func makeBlock() *types.Block { parentHash := common.HexToHash("0x01") coinbase := common.HexToAddress("0x01") root := common.HexToHash("0x01") difficulty := common.Big1 nonce := uint64(1) block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, nil) txto := common.HexToAddress("0x02") txamount := big.NewInt(1) txgasAmount := big.NewInt(1) txgasPrice := big.NewInt(1) txdata := []byte{1, 2, 3} tx := types.NewTransactionMessage(txto, txamount, txgasAmount, txgasPrice, txdata) txs := make([]*types.Transaction, 1) txs[0] = tx block.SetTransactions(txs) uncles := make([]*types.Header, 1) uncles[0] = makeHeader() block.SetUncles(uncles) return block }
// Block creation & chain handling func (bc *ChainManager) NewBlock(coinbase common.Address) *types.Block { bc.mu.RLock() defer bc.mu.RUnlock() var ( root common.Hash parentHash common.Hash ) if bc.currentBlock != nil { root = bc.currentBlock.Header().Root parentHash = bc.lastBlockHash } block := types.NewBlock( parentHash, coinbase, root, common.BigPow(2, 32), 0, nil) block.SetUncles(nil) block.SetTransactions(nil) block.SetReceipts(nil) parent := bc.currentBlock if parent != nil { header := block.Header() header.Difficulty = CalcDifficulty(block.Header(), parent.Header()) header.Number = new(big.Int).Add(parent.Header().Number, common.Big1) header.GasLimit = CalcGasLimit(parent) } return block }
// Tests that if a peer returns an invalid chain with a block pointing to a non- // existing parent, it is correctly detected and handled. func TestNonExistingParentAttack60(t *testing.T) { tester := newTester() // Forge a single-link chain with a forged header hashes, blocks := makeChain(1, 0, genesis) tester.newPeer("valid", eth60, hashes, blocks) wrongblock := types.NewBlock(&types.Header{}, nil, nil, nil) wrongblock.Td = blocks[hashes[0]].Td hashes, blocks = makeChain(1, 0, wrongblock) tester.newPeer("attack", eth60, hashes, blocks) // Try and sync with the malicious node and check that it fails if err := tester.sync("attack", nil); err == nil { t.Fatalf("block synchronization succeeded") } if tester.hasBlock(hashes[0]) { t.Fatalf("tester accepted unknown-parent block: %v", blocks[hashes[0]]) } // Try to synchronize with the valid chain and make sure it succeeds if err := tester.sync("valid", nil); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } if !tester.hasBlock(tester.peerHashes["valid"][0]) { t.Fatalf("tester didn't accept known-parent block: %v", tester.peerBlocks["valid"][hashes[0]]) } }
// GenesisBlock creates a genesis block with the given nonce. func GenesisBlock(nonce uint64, db common.Database) *types.Block { var accounts map[string]struct { Balance string Code string } err := json.Unmarshal(GenesisAccounts, &accounts) if err != nil { fmt.Println("unable to decode genesis json data:", err) os.Exit(1) } statedb := state.New(common.Hash{}, db) for addr, account := range accounts { codedAddr := common.Hex2Bytes(addr) accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr)) accountState.SetBalance(common.Big(account.Balance)) accountState.SetCode(common.FromHex(account.Code)) statedb.UpdateStateObject(accountState) } statedb.Sync() block := types.NewBlock(&types.Header{ Difficulty: params.GenesisDifficulty, GasLimit: params.GenesisGasLimit, Nonce: types.EncodeNonce(nonce), Root: statedb.Root(), }, nil, nil, nil) block.Td = params.GenesisDifficulty return block }
func GPUBench(gpuid uint64) { e := ethash.NewCL([]int{int(gpuid)}) var h common.Hash bogoHeader := &types.Header{ ParentHash: h, Number: big.NewInt(int64(42)), Difficulty: big.NewInt(int64(999999999999999)), } bogoBlock := types.NewBlock(bogoHeader, nil, nil, nil) err := ethash.InitCL(bogoBlock.NumberU64(), e) if err != nil { fmt.Println("OpenCL init error: ", err) return } stopChan := make(chan struct{}) reportHashRate := func() { for { time.Sleep(3 * time.Second) fmt.Printf("hashes/s : %v\n", e.GetHashrate()) } } fmt.Printf("Starting benchmark (%v seconds)\n", 60) go reportHashRate() go e.Search(bogoBlock, stopChan, 0) time.Sleep(60 * time.Second) fmt.Println("OK.") }
func newChain(size int) (chain []*types.Block) { var parentHash common.Hash for i := 0; i < size; i++ { head := &types.Header{ParentHash: parentHash, Number: big.NewInt(int64(i))} block := types.NewBlock(head, nil, nil, nil) chain = append(chain, block) parentHash = block.Hash() } return chain }
func newChain(size int) (chain []*types.Block) { var parentHash common.Hash for i := 0; i < size; i++ { block := types.NewBlock(parentHash, common.Address{}, common.Hash{}, new(big.Int), 0, nil) block.Header().Number = big.NewInt(int64(i)) chain = append(chain, block) parentHash = block.Hash() } return }
// GenesisBlockForTesting creates a block in which addr has the given wei balance. // The state trie of the block is written to db. func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { statedb := state.New(common.Hash{}, db) obj := statedb.GetOrNewStateObject(addr) obj.SetBalance(balance) statedb.SyncObjects() statedb.Sync() block := types.NewBlock(&types.Header{ Difficulty: params.GenesisDifficulty, GasLimit: params.GenesisGasLimit, Root: statedb.Root(), }, nil, nil, nil) return block }
func (self *worker) pendingBlock() *types.Block { self.currentMu.Lock() defer self.currentMu.Unlock() if atomic.LoadInt32(&self.mining) == 0 { return types.NewBlock( self.current.header, self.current.txs, nil, self.current.receipts, ) } return self.current.block }
func (self *worker) pending() (*types.Block, *state.StateDB) { self.currentMu.Lock() defer self.currentMu.Unlock() if atomic.LoadInt32(&self.mining) == 0 { return types.NewBlock( self.current.header, self.current.txs, nil, self.current.receipts, ), self.current.state } return self.current.Block, self.current.state }
// GenesisBlockForTesting creates a block in which addr has the given wei balance. // The state trie of the block is written to db. the passed db needs to contain a state root func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { statedb, _ := state.New(common.Hash{}, db) obj := statedb.GetOrNewStateObject(addr) obj.SetBalance(balance) root, err := statedb.Commit() if err != nil { panic(fmt.Sprintf("cannot write state: %v", err)) } block := types.NewBlock(&types.Header{ Difficulty: params.GenesisDifficulty, GasLimit: params.GenesisGasLimit, Root: root, }, nil, nil, nil) return block }
// block time is fixed at 10 seconds func newBlockFromParent(addr common.Address, parent *types.Block) *types.Block { block := types.NewBlock(parent.Hash(), addr, parent.Root(), common.BigPow(2, 32), 0, nil) block.SetUncles(nil) block.SetTransactions(nil) block.SetReceipts(nil) header := block.Header() header.Difficulty = CalcDifficulty(block.Header(), parent.Header()) header.Number = new(big.Int).Add(parent.Header().Number, common.Big1) header.Time = parent.Header().Time + 10 header.GasLimit = CalcGasLimit(parent) block.Td = parent.Td return block }
// GenerateChain creates a chain of n blocks. The first block's // parent will be the provided parent. db is used to store // intermediate states and should contain the parent's state trie. // // The generator function is called with a new block generator for // every block. Any transactions and uncles added to the generator // become part of the block. If gen is nil, the blocks will be empty // and their coinbase will be the zero address. // // Blocks created by GenerateChain do not contain valid proof of work // values. Inserting them into BlockChain requires use of FakePow or // a similar non-validating proof of work implementation. func GenerateChain(config *ChainConfig, parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) { b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb} // Mutate the state and block according to any hard-fork specs if config == nil { config = MakeChainConfig() } if daoBlock := config.DAOForkBlock; daoBlock != nil { limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) if h.Number.Cmp(daoBlock) >= 0 && h.Number.Cmp(limit) < 0 { if config.DAOForkSupport { h.Extra = common.CopyBytes(params.DAOForkBlockExtra) } } } if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(h.Number) == 0 { ApplyDAOHardFork(statedb) } // Execute any user modifications to the block and finalize it if gen != nil { gen(i, b) } AccumulateRewards(statedb, h, b.uncles) root, err := statedb.Commit() if err != nil { panic(fmt.Sprintf("state write error: %v", err)) } h.Root = root return types.NewBlock(h, b.txs, b.uncles, b.receipts), b.receipts } for i := 0; i < n; i++ { statedb, err := state.New(parent.Root(), db) if err != nil { panic(err) } header := makeHeader(parent, statedb) block, receipt := genblock(i, header, statedb) blocks[i] = block receipts[i] = receipt parent = block } return blocks, receipts }
// GenerateChain creates a chain of n blocks. The first block's // parent will be the provided parent. db is used to store // intermediate states and should contain the parent's state trie. // // The generator function is called with a new block generator for // every block. Any transactions and uncles added to the generator // become part of the block. If gen is nil, the blocks will be empty // and their coinbase will be the zero address. // // Blocks created by GenerateChain do not contain valid proof of work // values. Inserting them into ChainManager requires use of FakePow or // a similar non-validating proof of work implementation. func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) []*types.Block { statedb := state.New(parent.Root(), db) blocks := make(types.Blocks, n) genblock := func(i int, h *types.Header) *types.Block { b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb} if gen != nil { gen(i, b) } AccumulateRewards(statedb, h, b.uncles) statedb.SyncIntermediate() h.Root = statedb.Root() return types.NewBlock(h, b.txs, b.uncles, b.receipts) } for i := 0; i < n; i++ { header := makeHeader(parent, statedb) block := genblock(i, header) blocks[i] = block parent = block } return blocks }
// Tests that transactions and associated metadata can be stored and retrieved. func TestTransactionStorage(t *testing.T) { db, _ := ethdb.NewMemDatabase() tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11}) tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22}) tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), big.NewInt(3333), big.NewInt(33333), []byte{0x33, 0x33, 0x33}) txs := []*types.Transaction{tx1, tx2, tx3} block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil) // Check that no transactions entries are in a pristine database for i, tx := range txs { if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil { t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn) } } // Insert all the transactions into the database, and verify contents if err := WriteTransactions(db, block); err != nil { t.Fatalf("failed to write transactions: %v", err) } for i, tx := range txs { if txn, hash, number, index := GetTransaction(db, tx.Hash()); txn == nil { t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) } else { if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) } if tx.String() != txn.String() { t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) } } } // Delete the transactions and check purge for i, tx := range txs { DeleteTransaction(db, tx.Hash()) if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil { t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) } } }
// Tests that feeding bad blocks will result in a peer drop. func TestBlockAttackerDropping(t *testing.T) { // Define the disconnection requirement for individual block import errors tests := []struct { failure bool drop bool }{ {true, true}, {false, false}, } // Run the tests and check disconnection status tester := newTester() for i, tt := range tests { // Register a new peer and ensure it's presence id := fmt.Sprintf("test %d", i) if err := tester.newPeer(id, eth60, []common.Hash{common.Hash{}}, nil); err != nil { t.Fatalf("test %d: failed to register new peer: %v", i, err) } if _, ok := tester.peerHashes[id]; !ok { t.Fatalf("test %d: registered peer not found", i) } // Assemble a good or bad block, depending of the test raw := core.GenerateChain(genesis, testdb, 1, nil)[0] if tt.failure { parent := types.NewBlock(&types.Header{}, nil, nil, nil) raw = core.GenerateChain(parent, testdb, 1, nil)[0] } block := &Block{OriginPeer: id, RawBlock: raw} // Simulate block processing and check the result tester.downloader.queue.blockCache[0] = block tester.downloader.process() if _, ok := tester.peerHashes[id]; !ok != tt.drop { t.Errorf("test %d: peer drop mismatch for %v: have %v, want %v", i, tt.failure, !ok, tt.drop) } } }
func GenesisBlock(db common.Database) *types.Block { genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, params.GenesisDifficulty, 42, nil) genesis.Header().Number = common.Big0 genesis.Header().GasLimit = params.GenesisGasLimit genesis.Header().GasUsed = common.Big0 genesis.Header().Time = 0 genesis.Td = common.Big0 genesis.SetUncles([]*types.Header{}) genesis.SetTransactions(types.Transactions{}) genesis.SetReceipts(types.Receipts{}) var accounts map[string]struct { Balance string Code string } err := json.Unmarshal(GenesisData, &accounts) if err != nil { fmt.Println("enable to decode genesis json data:", err) os.Exit(1) } statedb := state.New(genesis.Root(), db) for addr, account := range accounts { codedAddr := common.Hex2Bytes(addr) accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr)) accountState.SetBalance(common.Big(account.Balance)) accountState.SetCode(common.FromHex(account.Code)) statedb.UpdateStateObject(accountState) } statedb.Sync() genesis.Header().Root = statedb.Root() genesis.Td = params.GenesisDifficulty return genesis }
"sync" "sync/atomic" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" ) var ( testdb, _ = ethdb.NewMemDatabase() genesis = core.GenesisBlockForTesting(testdb, common.Address{}, big.NewInt(0)) unknownBlock = types.NewBlock(&types.Header{GasLimit: params.GenesisGasLimit}, nil, nil, nil) ) // makeChain creates a chain of n blocks starting at and including parent. // the returned hash chain is ordered head->parent. func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) { blocks := core.GenerateChain(parent, testdb, n, func(i int, gen *core.BlockGen) { gen.SetCoinbase(common.Address{seed}) }) hashes := make([]common.Hash, n+1) hashes[len(hashes)-1] = parent.Hash() blockm := make(map[common.Hash]*types.Block, n+1) blockm[parent.Hash()] = parent for i, b := range blocks { hashes[len(hashes)-i-2] = b.Hash() blockm[b.Hash()] = b
func (self *worker) commitNewWork() { self.mu.Lock() defer self.mu.Unlock() self.uncleMu.Lock() defer self.uncleMu.Unlock() self.currentMu.Lock() defer self.currentMu.Unlock() tstart := time.Now() parent := self.chain.CurrentBlock() tstamp := tstart.Unix() if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 { tstamp = parent.Time().Int64() + 1 } // this will ensure we're not going off too far in the future if now := time.Now().Unix(); tstamp > now+4 { wait := time.Duration(tstamp-now) * time.Second glog.V(logger.Info).Infoln("We are too far in the future. Waiting for", wait) time.Sleep(wait) } num := parent.Number() header := &types.Header{ ParentHash: parent.Hash(), Number: num.Add(num, common.Big1), Difficulty: core.CalcDifficulty(self.config, uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()), GasLimit: core.CalcGasLimit(parent), GasUsed: new(big.Int), Coinbase: self.coinbase, Extra: self.extra, Time: big.NewInt(tstamp), } previous := self.current // Could potentially happen if starting to mine in an odd state. err := self.makeCurrent(parent, header) if err != nil { glog.V(logger.Info).Infoln("Could not create new env for mining, retrying on next block.") return } work := self.current /* //approach 1 transactions := self.eth.TxPool().GetTransactions() sort.Sort(types.TxByNonce(transactions)) */ //approach 2 transactions := self.eth.TxPool().GetTransactions() types.SortByPriceAndNonce(transactions) /* // approach 3 // commit transactions for this run. txPerOwner := make(map[common.Address]types.Transactions) // Sort transactions by owner for _, tx := range self.eth.TxPool().GetTransactions() { from, _ := tx.From() // we can ignore the sender error txPerOwner[from] = append(txPerOwner[from], tx) } var ( singleTxOwner types.Transactions multiTxOwner types.Transactions ) // Categorise transactions by // 1. 1 owner tx per block // 2. multi txs owner per block for _, txs := range txPerOwner { if len(txs) == 1 { singleTxOwner = append(singleTxOwner, txs[0]) } else { multiTxOwner = append(multiTxOwner, txs...) } } sort.Sort(types.TxByPrice(singleTxOwner)) sort.Sort(types.TxByNonce(multiTxOwner)) transactions := append(singleTxOwner, multiTxOwner...) */ work.commitTransactions(self.mux, transactions, self.gasPrice, self.chain) self.eth.TxPool().RemoveTransactions(work.lowGasTxs) // compute uncles for the new block. var ( uncles []*types.Header badUncles []common.Hash ) for hash, uncle := range self.possibleUncles { if len(uncles) == 2 { break } if err := self.commitUncle(work, uncle.Header()); err != nil { if glog.V(logger.Ridiculousness) { glog.V(logger.Detail).Infof("Bad uncle found and will be removed (%x)\n", hash[:4]) glog.V(logger.Detail).Infoln(uncle) } badUncles = append(badUncles, hash) } else { glog.V(logger.Debug).Infof("commiting %x as uncle\n", hash[:4]) uncles = append(uncles, uncle.Header()) } } for _, hash := range badUncles { delete(self.possibleUncles, hash) } if atomic.LoadInt32(&self.mining) == 1 { // commit state root after all state transitions. core.AccumulateRewards(work.state, header, uncles) header.Root = work.state.IntermediateRoot() } // create the new block whose nonce will be mined. work.Block = types.NewBlock(header, work.txs, uncles, work.receipts) // We only care about logging if we're actually mining. if atomic.LoadInt32(&self.mining) == 1 { glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", work.Block.Number(), work.tcount, len(uncles), time.Since(tstart)) self.logLocalMinedBlocks(work, previous) } self.push(work) }
"math/big" "sync" "sync/atomic" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" ) var ( testdb, _ = ethdb.NewMemDatabase() genesis = core.GenesisBlockForTesting(testdb, common.Address{}, big.NewInt(0)) unknownBlock = types.NewBlock(&types.Header{}, nil, nil, nil) ) // makeChain creates a chain of n blocks starting at and including parent. // the returned hash chain is ordered head->parent. func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) { blocks := core.GenerateChain(parent, testdb, n, func(i int, gen *core.BlockGen) { gen.SetCoinbase(common.Address{seed}) }) hashes := make([]common.Hash, n+1) hashes[len(hashes)-1] = parent.Hash() blockm := make(map[common.Hash]*types.Block, n+1) blockm[parent.Hash()] = parent for i, b := range blocks { hashes[len(hashes)-i-2] = b.Hash() blockm[b.Hash()] = b
// WriteGenesisBlock writes the genesis block to the database as block number 0 func WriteGenesisBlock(stateDb, blockDb common.Database, reader io.Reader) (*types.Block, error) { contents, err := ioutil.ReadAll(reader) if err != nil { return nil, err } var genesis struct { Nonce string Timestamp string ParentHash string ExtraData string GasLimit string Difficulty string Mixhash string Coinbase string Alloc map[string]struct { Code string Storage map[string]string Balance string } } if err := json.Unmarshal(contents, &genesis); err != nil { return nil, err } statedb := state.New(common.Hash{}, stateDb) for addr, account := range genesis.Alloc { address := common.HexToAddress(addr) statedb.AddBalance(address, common.String2Big(account.Balance)) statedb.SetCode(address, common.Hex2Bytes(account.Code)) for key, value := range account.Storage { statedb.SetState(address, common.HexToHash(key), common.HexToHash(value)) } } statedb.SyncObjects() difficulty := common.String2Big(genesis.Difficulty) block := types.NewBlock(&types.Header{ Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()), Time: common.String2Big(genesis.Timestamp).Uint64(), ParentHash: common.HexToHash(genesis.ParentHash), Extra: common.FromHex(genesis.ExtraData), GasLimit: common.String2Big(genesis.GasLimit), Difficulty: difficulty, MixDigest: common.HexToHash(genesis.Mixhash), Coinbase: common.HexToAddress(genesis.Coinbase), Root: statedb.Root(), }, nil, nil, nil) block.Td = difficulty if block := GetBlockByHash(blockDb, block.Hash()); block != nil { glog.V(logger.Info).Infoln("Genesis block already in chain. Writing canonical number") err := WriteCanonNumber(blockDb, block) if err != nil { return nil, err } return block, nil } statedb.Sync() err = WriteBlock(blockDb, block) if err != nil { return nil, err } err = WriteHead(blockDb, block) if err != nil { return nil, err } return block, nil }
// WriteGenesisBlock writes the genesis block to the database as block number 0 func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, error) { contents, err := ioutil.ReadAll(reader) if err != nil { return nil, err } var genesis struct { ChainConfig *ChainConfig `json:"config"` Nonce string Timestamp string ParentHash string ExtraData string GasLimit string Difficulty string Mixhash string Coinbase string Alloc map[string]struct { Code string Storage map[string]string Balance string } } if err := json.Unmarshal(contents, &genesis); err != nil { return nil, err } // creating with empty hash always works statedb, _ := state.New(common.Hash{}, chainDb) for addr, account := range genesis.Alloc { address := common.HexToAddress(addr) statedb.AddBalance(address, common.String2Big(account.Balance)) statedb.SetCode(address, common.Hex2Bytes(account.Code)) for key, value := range account.Storage { statedb.SetState(address, common.HexToHash(key), common.HexToHash(value)) } } root, stateBatch := statedb.CommitBatch() difficulty := common.String2Big(genesis.Difficulty) block := types.NewBlock(&types.Header{ Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()), Time: common.String2Big(genesis.Timestamp), ParentHash: common.HexToHash(genesis.ParentHash), Extra: common.FromHex(genesis.ExtraData), GasLimit: common.String2Big(genesis.GasLimit), Difficulty: difficulty, MixDigest: common.HexToHash(genesis.Mixhash), Coinbase: common.HexToAddress(genesis.Coinbase), Root: root, }, nil, nil, nil) if block := GetBlock(chainDb, block.Hash()); block != nil { glog.V(logger.Info).Infoln("Genesis block already in chain. Writing canonical number") err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) if err != nil { return nil, err } return block, nil } if err := stateBatch.Write(); err != nil { return nil, fmt.Errorf("cannot write state: %v", err) } if err := WriteTd(chainDb, block.Hash(), difficulty); err != nil { return nil, err } if err := WriteBlock(chainDb, block); err != nil { return nil, err } if err := WriteBlockReceipts(chainDb, block.Hash(), nil); err != nil { return nil, err } if err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()); err != nil { return nil, err } if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil { return nil, err } if err := WriteChainConfig(chainDb, block.Hash(), genesis.ChainConfig); err != nil { return nil, err } return block, nil }
func (self *worker) commitNewWork() { self.mu.Lock() defer self.mu.Unlock() self.uncleMu.Lock() defer self.uncleMu.Unlock() self.currentMu.Lock() defer self.currentMu.Unlock() tstart := time.Now() parent := self.chain.CurrentBlock() tstamp := tstart.Unix() if tstamp <= parent.Time() { tstamp = parent.Time() + 1 } // this will ensure we're not going off too far in the future if now := time.Now().Unix(); tstamp > now+4 { wait := time.Duration(tstamp-now) * time.Second glog.V(logger.Info).Infoln("We are too far in the future. Waiting for", wait) time.Sleep(wait) } num := parent.Number() header := &types.Header{ ParentHash: parent.Hash(), Number: num.Add(num, common.Big1), Difficulty: core.CalcDifficulty(tstamp, parent.Time(), parent.Difficulty()), GasLimit: core.CalcGasLimit(parent), GasUsed: new(big.Int), Coinbase: self.coinbase, Extra: self.extra, Time: uint64(tstamp), } previous := self.current self.makeCurrent(parent, header) current := self.current // commit transactions for this run. transactions := self.eth.TxPool().GetTransactions() sort.Sort(types.TxByNonce{transactions}) current.coinbase.SetGasLimit(header.GasLimit) current.commitTransactions(transactions, self.gasPrice, self.proc) self.eth.TxPool().RemoveTransactions(current.lowGasTxs) // compute uncles for the new block. var ( uncles []*types.Header badUncles []common.Hash ) for hash, uncle := range self.possibleUncles { if len(uncles) == 2 { break } if err := self.commitUncle(uncle.Header()); err != nil { if glog.V(logger.Ridiculousness) { glog.V(logger.Detail).Infof("Bad uncle found and will be removed (%x)\n", hash[:4]) glog.V(logger.Detail).Infoln(uncle) } badUncles = append(badUncles, hash) } else { glog.V(logger.Debug).Infof("commiting %x as uncle\n", hash[:4]) uncles = append(uncles, uncle.Header()) } } for _, hash := range badUncles { delete(self.possibleUncles, hash) } if atomic.LoadInt32(&self.mining) == 1 { // commit state root after all state transitions. core.AccumulateRewards(self.current.state, header, uncles) current.state.Update() self.current.state.Sync() header.Root = current.state.Root() } // create the new block whose nonce will be mined. current.block = types.NewBlock(header, current.txs, uncles, current.receipts) self.current.block.Td = new(big.Int).Set(core.CalcTD(self.current.block, self.chain.GetBlock(self.current.block.ParentHash()))) // We only care about logging if we're actually mining. if atomic.LoadInt32(&self.mining) == 1 { glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", current.block.Number(), current.tcount, len(uncles), time.Since(tstart)) self.logLocalMinedBlocks(previous) } self.push() }