func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value { var block *types.Block if len(call.ArgumentList) > 0 { if call.Argument(0).IsNumber() { num, _ := call.Argument(0).ToInteger() block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num)) } else if call.Argument(0).IsString() { hash, _ := call.Argument(0).ToString() block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash)) } else { fmt.Println("invalid argument for dump. Either hex string or number") } } else { block = js.ethereum.ChainManager().CurrentBlock() } if block == nil { fmt.Println("block not found") return otto.UndefinedValue() } statedb := state.New(block.Root(), js.ethereum.StateDb()) dump := statedb.RawDump() return js.re.ToVal(dump) }
// 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 (self *Gui) DumpState(hash, path string) { var stateDump []byte if len(hash) == 0 { stateDump = self.eth.ChainManager().State().Dump() } else { var block *types.Block if hash[0] == '#' { i, _ := strconv.Atoi(hash[1:]) block = self.eth.ChainManager().GetBlockByNumber(uint64(i)) } else { block = self.eth.ChainManager().GetBlock(common.HexToHash(hash)) } if block == nil { guilogger.Infof("block err: not found %s\n", hash) return } stateDump = state.New(block.Root(), self.eth.StateDb()).Dump() } file, err := os.OpenFile(path[7:], os.O_CREATE|os.O_RDWR, os.ModePerm) if err != nil { guilogger.Infoln("dump err: ", err) return } defer file.Close() guilogger.Infof("dumped state (%s) to %s\n", hash, path) file.Write(stateDump) }
// makeCurrent creates a new environment for the current cycle. func (self *worker) makeCurrent(parent *types.Block, header *types.Header) { state := state.New(parent.Root(), self.eth.ChainDb()) work := &Work{ state: state, ancestors: set.New(), family: set.New(), uncles: set.New(), header: header, coinbase: state.GetOrNewStateObject(self.coinbase), createdAt: time.Now(), } // when 08 is processed ancestors contain 07 (quick block) for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) { for _, uncle := range ancestor.Uncles() { work.family.Add(uncle.Hash()) } work.family.Add(ancestor.Hash()) work.ancestors.Add(ancestor.Hash()) } accounts, _ := self.eth.AccountManager().Accounts() // Keep track of transactions which return errors so they can be removed work.remove = set.New() work.tcount = 0 work.ignoredTransactors = set.New() work.lowGasTransactors = set.New() work.ownedAccounts = accountAddressesSet(accounts) if self.current != nil { work.localMinedBlocks = self.current.localMinedBlocks } self.current = work }
func env(block *types.Block, eth core.Backend) *environment { state := state.New(block.Root(), eth.StateDb()) env := &environment{ totalUsedGas: new(big.Int), state: state, block: block, family: set.New(), uncles: set.New(), coinbase: state.GetOrNewStateObject(block.Coinbase()), } return env }
// 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 }
// Process block will attempt to process the given block's transactions and applies them // on top of the block's parent state (given it exists) and will return wether it was // successful or not. func (sm *BlockProcessor) Process(block *types.Block) (logs vm.Logs, receipts types.Receipts, err error) { // Processing a blocks may never happen simultaneously sm.mutex.Lock() defer sm.mutex.Unlock() if sm.bc.HasBlock(block.Hash()) { if _, err := state.New(block.Root(), sm.chainDb); err == nil { return nil, nil, &KnownBlockError{block.Number(), block.Hash()} } } if parent := sm.bc.GetBlock(block.ParentHash()); parent != nil { if _, err := state.New(parent.Root(), sm.chainDb); err == nil { return sm.processWithParent(block, parent) } } return nil, nil, ParentError(block.ParentHash()) }
// WriteBlock writes the block to the chain (or pending queue) func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status writeStatus, err error) { self.wg.Add(1) defer self.wg.Done() cblock := self.currentBlock // Compare the TD of the last known block in the canonical chain to make sure it's greater. // At this point it's possible that a different chain (fork) becomes the new canonical chain. if block.Td.Cmp(self.Td()) > 0 { // chain fork if block.ParentHash() != cblock.Hash() { // during split we merge two different chains and create the new canonical chain err := self.merge(cblock, block) if err != nil { return nonStatTy, err } status = splitStatTy } self.mu.Lock() self.setTotalDifficulty(block.Td) self.insert(block) self.mu.Unlock() self.setTransState(state.New(block.Root(), self.stateDb)) self.txState.SetState(state.New(block.Root(), self.stateDb)) status = canonStatTy } else { status = sideStatTy } if queued { // Write block to database. Eventually we'll have to improve on this and throw away blocks that are // not in the canonical chain. self.mu.Lock() self.enqueueForWrite(block) self.mu.Unlock() } else { self.write(block) } // Delete from future blocks self.futureBlocks.Remove(block.Hash()) return }
// 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 }
func dump(ctx *cli.Context) { chain, _, stateDB, _ := utils.MakeChain(ctx) for _, arg := range ctx.Args() { var block *types.Block if hashish(arg) { block = chain.GetBlock(common.HexToHash(arg)) } else { num, _ := strconv.Atoi(arg) block = chain.GetBlockByNumber(uint64(num)) } if block == nil { fmt.Println("{}") utils.Fatalf("block not found") } else { state := state.New(block.Root(), stateDB) fmt.Printf("%s\n", state.Dump()) } } }
func (bc *ChainManager) SetHead(head *types.Block) { bc.mu.Lock() defer bc.mu.Unlock() for block := bc.currentBlock; block != nil && block.Hash() != head.Hash(); block = bc.GetBlock(block.Header().ParentHash) { bc.removeBlock(block) } bc.cache = NewBlockCache(blockCacheLimit) bc.currentBlock = head bc.makeCache() statedb := state.New(head.Root(), bc.stateDb) bc.txState = state.ManageState(statedb) bc.transState = statedb.Copy() bc.setTotalDifficulty(head.Td) bc.insert(head) bc.setLastState() }
func NewBlockRes(block *types.Block, td *big.Int, fullTx bool) *BlockRes { if block == nil { return nil } res := new(BlockRes) res.fullTx = fullTx res.BlockNumber = newHexNum(block.Number()) res.BlockHash = newHexData(block.Hash()) res.ParentHash = newHexData(block.ParentHash()) res.Nonce = newHexData(block.Nonce()) res.Sha3Uncles = newHexData(block.UncleHash()) res.LogsBloom = newHexData(block.Bloom()) res.TransactionRoot = newHexData(block.TxHash()) res.StateRoot = newHexData(block.Root()) res.ReceiptRoot = newHexData(block.ReceiptHash()) res.Miner = newHexData(block.Coinbase()) res.Difficulty = newHexNum(block.Difficulty()) res.TotalDifficulty = newHexNum(td) res.Size = newHexNum(block.Size().Int64()) res.ExtraData = newHexData(block.Extra()) res.GasLimit = newHexNum(block.GasLimit()) res.GasUsed = newHexNum(block.GasUsed()) res.UnixTimestamp = newHexNum(block.Time()) txs := block.Transactions() res.Transactions = make([]*TransactionRes, len(txs)) for i, tx := range txs { res.Transactions[i] = NewTransactionRes(tx) res.Transactions[i].BlockHash = res.BlockHash res.Transactions[i].BlockNumber = res.BlockNumber res.Transactions[i].TxIndex = newHexNum(i) } uncles := block.Uncles() res.Uncles = make([]*UncleRes, len(uncles)) for i, uncle := range uncles { res.Uncles[i] = NewUncleRes(uncle) } return res }
// WriteBlock writes the block to the chain (or pending queue) func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status writeStatus, err error) { self.wg.Add(1) defer self.wg.Done() cblock := self.currentBlock // Compare the TD of the last known block in the canonical chain to make sure it's greater. // At this point it's possible that a different chain (fork) becomes the new canonical chain. if block.Td.Cmp(self.Td()) > 0 { // chain fork if block.ParentHash() != cblock.Hash() { // during split we merge two different chains and create the new canonical chain err := self.merge(cblock, block) if err != nil { return NonStatTy, err } status = SplitStatTy } self.mu.Lock() self.setTotalDifficulty(block.Td) self.insert(block) self.mu.Unlock() self.setTransState(state.New(block.Root(), self.stateDb)) self.txState.SetState(state.New(block.Root(), self.stateDb)) status = CanonStatTy } else { status = SideStatTy } err = WriteBlock(self.blockDb, block) if err != nil { glog.Fatalln("db err:", err) } // Delete from future blocks self.futureBlocks.Remove(block.Hash()) return }
// 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 }
// ValidateBlock validates the given block's header and uncles and verifies the // the block header's transaction and uncle roots. // // ValidateBlock does not validate the header's pow. The pow work validated // separately so we can process them in parallel. // // ValidateBlock also validates and makes sure that any previous state (or present) // state that might or might not be present is checked to make sure that fast // sync has done it's job proper. This prevents the block validator form accepting // false positives where a header is present but the state is not. func (v *BlockValidator) ValidateBlock(block *types.Block) error { if v.bc.HasBlock(block.Hash()) { if _, err := state.New(block.Root(), v.bc.chainDb); err == nil { return &KnownBlockError{block.Number(), block.Hash()} } } parent := v.bc.GetBlock(block.ParentHash()) if parent == nil { return ParentError(block.ParentHash()) } if _, err := state.New(parent.Root(), v.bc.chainDb); err != nil { return ParentError(block.ParentHash()) } header := block.Header() // validate the block header if err := ValidateHeader(v.config, v.Pow, header, parent.Header(), false, false); err != nil { return err } // verify the uncles are correctly rewarded if err := v.VerifyUncles(block, parent); err != nil { return err } // Verify UncleHash before running other uncle validations unclesSha := types.CalcUncleHash(block.Uncles()) if unclesSha != header.UncleHash { return fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha) } // The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]])) // can be used by light clients to make sure they've received the correct Txs txSha := types.DeriveSha(block.Transactions()) if txSha != header.TxHash { return fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha) } return nil }
func dump(ctx *cli.Context) { chain, chainDb := utils.MakeChain(ctx) for _, arg := range ctx.Args() { var block *types.Block if hashish(arg) { block = chain.GetBlock(common.HexToHash(arg)) } else { num, _ := strconv.Atoi(arg) block = chain.GetBlockByNumber(uint64(num)) } if block == nil { fmt.Println("{}") utils.Fatalf("block not found") } else { state, err := state.New(block.Root(), chainDb) if err != nil { utils.Fatalf("could not create new state: %v", err) return } fmt.Printf("%s\n", state.Dump()) } } chainDb.Close() }
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, receipts types.Receipts, err error) { // Create a new state based on the parent's root (e.g., create copy) state := state.New(parent.Root(), sm.chainDb) header := block.Header() uncles := block.Uncles() txs := block.Transactions() // Block validation if err = ValidateHeader(sm.Pow, header, parent.Header(), false, false); err != nil { return } // There can be at most two uncles if len(uncles) > 2 { return nil, nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles)) } receipts, err = sm.TransitionState(state, parent, block, false) if err != nil { return } // Validate the received block's bloom with the one derived from the generated receipts. // For valid blocks this should always validate to true. rbloom := types.CreateBloom(receipts) if rbloom != header.Bloom { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return } // The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]])) // can be used by light clients to make sure they've received the correct Txs txSha := types.DeriveSha(txs) if txSha != header.TxHash { err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha) return } // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]])) receiptSha := types.DeriveSha(receipts) if receiptSha != header.ReceiptHash { err = fmt.Errorf("invalid receipt root hash. received=%x calculated=%x", header.ReceiptHash, receiptSha) return } // Verify UncleHash before running other uncle validations unclesSha := types.CalcUncleHash(uncles) if unclesSha != header.UncleHash { err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha) return } // Verify uncles if err = sm.VerifyUncles(state, block, parent); err != nil { return } // Accumulate static rewards; block reward, uncle's and uncle inclusion. AccumulateRewards(state, header, uncles) // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. state.SyncObjects() if header.Root != state.Root() { err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return } // Sync the current block's state to the database state.Sync() return state.Logs(), receipts, nil }
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) { sm.lastAttemptedBlock = block // Create a new state based on the parent's root (e.g., create copy) state := state.New(parent.Root(), sm.db) // Block validation if err = sm.ValidateHeader(block.Header(), parent.Header()); err != nil { return } // There can be at most two uncles if len(block.Uncles()) > 2 { return nil, ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles())) } receipts, err := sm.TransitionState(state, parent, block, false) if err != nil { return } header := block.Header() // Validate the received block's bloom with the one derived from the generated receipts. // For valid blocks this should always validate to true. rbloom := types.CreateBloom(receipts) if rbloom != header.Bloom { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return } // The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]])) // can be used by light clients to make sure they've received the correct Txs txSha := types.DeriveSha(block.Transactions()) if txSha != header.TxHash { err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha) return } // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]])) receiptSha := types.DeriveSha(receipts) if receiptSha != header.ReceiptHash { err = fmt.Errorf("invalid receipt root hash. received=%x calculated=%x", header.ReceiptHash, receiptSha) return } // Verify UncleHash before running other uncle validations unclesSha := block.CalculateUnclesHash() if unclesSha != header.UncleHash { err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha) return } // Verify uncles if err = sm.VerifyUncles(state, block, parent); err != nil { return } // Accumulate static rewards; block reward, uncle's and uncle inclusion. AccumulateRewards(state, block) // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. state.Update() if header.Root != state.Root() { err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return } // Calculate the td for this block //td = CalculateTD(block, parent) // Sync the current block's state to the database state.Sync() // Remove transactions from the pool sm.txpool.RemoveTransactions(block.Transactions()) // This puts transactions in a extra db for rpc for i, tx := range block.Transactions() { putTx(sm.extraDb, tx, block, uint64(i)) } return state.Logs(), nil }