// ProcessBlock reprocesses an already owned block. func (api *PrivateDebugAPI) ProcessBlock(number uint64) (bool, error) { // Fetch the block that we aim to reprocess block := api.eth.BlockChain().GetBlockByNumber(number) if block == nil { return false, fmt.Errorf("block #%d not found", number) } // Temporarily enable debugging defer func(old bool) { vm.Debug = old }(vm.Debug) vm.Debug = true // Validate and reprocess the block var ( blockchain = api.eth.BlockChain() validator = blockchain.Validator() processor = blockchain.Processor() ) if err := core.ValidateHeader(blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil { return false, err } statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), api.eth.ChainDb()) if err != nil { return false, err } receipts, _, usedGas, err := processor.Process(block, statedb) if err != nil { return false, err } if err := validator.ValidateState(block, blockchain.GetBlock(block.ParentHash()), statedb, receipts, usedGas); err != nil { return false, err } return true, nil }
// 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) { 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} 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 }
// StorageAt returns the data stores in the state for the given address and location. func (be *registryAPIBackend) StorageAt(addr string, storageAddr string) string { block := be.bc.CurrentBlock() state, err := state.New(block.Root(), be.chainDb) if err != nil { return "" } return state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex() }
// HasBlockAndState checks if a block and associated state trie is fully present // in the database or not, caching it if present. func (bc *BlockChain) HasBlockAndState(hash common.Hash) bool { // Check first that the block itself is known block := bc.GetBlock(hash) if block == nil { return false } // Ensure the associated state is also present _, err := state.New(block.Root(), bc.chainDb) return err == nil }
// DumpBlock retrieves the entire state of the database at a given block. func (api *PublicDebugAPI) DumpBlock(number uint64) (state.World, error) { block := api.eth.BlockChain().GetBlockByNumber(number) if block == nil { return state.World{}, fmt.Errorf("block #%d not found", number) } stateDb, err := state.New(block.Root(), api.eth.ChainDb()) if err != nil { return state.World{}, err } return stateDb.RawDump(), nil }
// GetStorageAt returns the storage from the state at the given address, key and block number. func (s *PublicBlockChainAPI) GetStorageAt(address common.Address, key string, blockNr rpc.BlockNumber) (string, error) { if block := blockByNumber(s.miner, s.bc, blockNr); block != nil { state, err := state.New(block.Root(), s.chainDb) if err != nil { return "", err } return state.GetState(address, common.HexToHash(key)).Hex(), nil } return "0x", nil }
// GetBalance returns the amount of wei for the given address in the state of the given block number. // When block number equals rpc.LatestBlockNumber the current block is used. func (s *PublicBlockChainAPI) GetBalance(address common.Address, blockNr rpc.BlockNumber) (*big.Int, error) { block := blockByNumber(s.miner, s.bc, blockNr) if block == nil { return nil, nil } state, err := state.New(block.Root(), s.chainDb) if err != nil { return nil, err } return state.GetBalance(address), nil }
// GetTransactionCount returns the number of transactions the given address has sent for the given block number func (s *PublicTransactionPoolAPI) GetTransactionCount(address common.Address, blockNr rpc.BlockNumber) (*rpc.HexNumber, error) { block := blockByNumber(s.miner, s.bc, blockNr) if block == nil { return nil, nil } state, err := state.New(block.Root(), s.chainDb) if err != nil { return nil, err } return rpc.NewHexNumber(state.GetNonce(address)), nil }
// 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 // seperately so we can process them in paralel. // // 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.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 (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) { if block := blockByNumber(s.miner, s.bc, blockNr); block != nil { stateDb, err := state.New(block.Root(), s.chainDb) if err != nil { return "0x", nil, err } stateDb = stateDb.Copy() var from *state.StateObject if args.From == (common.Address{}) { accounts, err := s.am.Accounts() if err != nil || len(accounts) == 0 { from = stateDb.GetOrNewStateObject(common.Address{}) } else { from = stateDb.GetOrNewStateObject(accounts[0].Address) } } else { from = stateDb.GetOrNewStateObject(args.From) } from.SetBalance(common.MaxBig) msg := callmsg{ from: from, to: &args.To, gas: args.Gas.BigInt(), gasPrice: args.GasPrice.BigInt(), value: args.Value.BigInt(), data: common.FromHex(args.Data), } if msg.gas.Cmp(common.Big0) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(common.Big0) == 0 { msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) } header := s.bc.CurrentBlock().Header() vmenv := core.NewEnv(stateDb, s.bc, msg, header) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) if len(res) == 0 { // backwards compatability return "0x", gas, err } return common.ToHex(res), gas, err } return "0x", common.Big0, nil }
// Register registers a new content hash in the registry. func (api *PrivateRegistarAPI) Register(sender common.Address, addr common.Address, contentHashHex string) (bool, error) { block := api.be.bc.CurrentBlock() state, err := state.New(block.Root(), api.be.chainDb) if err != nil { return false, err } codeb := state.GetCode(addr) codeHash := common.BytesToHash(crypto.Sha3(codeb)) contentHash := common.HexToHash(contentHashHex) _, err = registrar.New(api.be).SetHashToHash(sender, codeHash, contentHash) return err == nil, err }
// GetData returns the data stored at the given address in the state for the given block number. func (s *PublicBlockChainAPI) GetData(address common.Address, blockNr rpc.BlockNumber) (string, error) { if block := blockByNumber(s.miner, s.bc, blockNr); block != nil { state, err := state.New(block.Root(), s.chainDb) if err != nil { return "", err } res := state.GetCode(address) if len(res) == 0 { // backwards compatibility return "0x", nil } return common.ToHex(res), nil } return "0x", nil }
// 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 }
// Call forms a transaction from the given arguments and tries to execute it on // a private VM with a copy of the state. Any changes are therefore only temporary // and not part of the actual state. This allows for local execution/queries. func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { block := be.bc.CurrentBlock() statedb, err := state.New(block.Root(), be.chainDb) if err != nil { return "", "", err } var from *state.StateObject if len(fromStr) == 0 { accounts, err := be.am.Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(accounts[0].Address) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetBalance(common.MaxBig) msg := callmsg{ from: from, gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if len(toStr) > 0 { addr := common.HexToAddress(toStr) msg.to = &addr } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) } header := be.bc.CurrentBlock().Header() vmenv := core.NewEnv(statedb, be.bc, msg, header) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) return common.ToHex(res), gas.String(), err }
// Execute executes the code using the input as call data during the execution. // It returns the EVM's return value, the new state and an error if it failed. // // Executes sets up a in memory, temporarily, environment for the execution of // the given code. It enabled the JIT by default and make sure that it's restored // to it's original state afterwards. func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { if cfg == nil { cfg = new(Config) } setDefaults(cfg) // defer the call to setting back the original values defer func(debug, forceJit, enableJit bool) { vm.Debug = debug vm.ForceJit = forceJit vm.EnableJit = enableJit }(vm.Debug, vm.ForceJit, vm.EnableJit) vm.ForceJit = !cfg.DisableJit vm.EnableJit = !cfg.DisableJit vm.Debug = cfg.Debug var ( db, _ = ethdb.NewMemDatabase() statedb, _ = state.New(common.Hash{}, db) vmenv = NewEnv(cfg, statedb) sender = statedb.CreateAccount(cfg.Origin) receiver = statedb.CreateAccount(common.StringToAddress("contract")) ) // set the receiver's (the executing contract) code for execution. receiver.SetCode(code) // Call the code with the given configuration. ret, err := vmenv.Call( sender, receiver.Address(), input, cfg.GasLimit, cfg.GasPrice, cfg.Value, ) if cfg.Debug { vm.StdErrFormat(vmenv.StructLogs()) } return ret, statedb, err }
// makeCurrent creates a new environment for the current cycle. func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error { state, err := state.New(parent.Root(), self.eth.ChainDb()) if err != nil { return err } work := &Work{ state: state, ancestors: set.New(), family: set.New(), uncles: set.New(), header: header, 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 return nil }
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned // it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go). func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { self.wg.Add(1) defer self.wg.Done() self.chainmu.Lock() defer self.chainmu.Unlock() // A queued approach to delivering events. This is generally // faster than direct delivery and requires much less mutex // acquiring. var ( stats struct{ queued, processed, ignored int } events = make([]interface{}, 0, len(chain)) coalescedLogs vm.Logs tstart = time.Now() nonceChecked = make([]bool, len(chain)) ) // Start the parallel nonce verifier. nonceAbort, nonceResults := verifyNoncesFromBlocks(self.pow, chain) defer close(nonceAbort) txcount := 0 for i, block := range chain { if atomic.LoadInt32(&self.procInterrupt) == 1 { glog.V(logger.Debug).Infoln("Premature abort during block chain processing") break } bstart := time.Now() // Wait for block i's nonce to be verified before processing // its state transition. for !nonceChecked[i] { r := <-nonceResults nonceChecked[r.index] = true if !r.valid { block := chain[r.index] return r.index, &BlockNonceErr{Hash: block.Hash(), Number: block.Number(), Nonce: block.Nonce()} } } if BadHashes[block.Hash()] { err := BadHashError(block.Hash()) reportBlock(block, err) return i, err } // Stage 1 validation of the block using the chain's validator // interface. err := self.Validator().ValidateBlock(block) if err != nil { if IsKnownBlockErr(err) { stats.ignored++ continue } if err == BlockFutureErr { // Allow up to MaxFuture second in the future blocks. If this limit // is exceeded the chain is discarded and processed at a later time // if given. max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks) if block.Time().Cmp(max) == 1 { return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max) } self.futureBlocks.Add(block.Hash(), block) stats.queued++ continue } if IsParentErr(err) && self.futureBlocks.Contains(block.ParentHash()) { self.futureBlocks.Add(block.Hash(), block) stats.queued++ continue } reportBlock(block, err) return i, err } // Create a new statedb using the parent block and report an // error if it fails. statedb, err := state.New(self.GetBlock(block.ParentHash()).Root(), self.chainDb) if err != nil { reportBlock(block, err) return i, err } // Process block using the parent state as reference point. receipts, logs, usedGas, err := self.processor.Process(block, statedb) if err != nil { reportBlock(block, err) return i, err } // Validate the state using the default validator err = self.Validator().ValidateState(block, self.GetBlock(block.ParentHash()), statedb, receipts, usedGas) if err != nil { reportBlock(block, err) return i, err } // Write state changes to database _, err = statedb.Commit() if err != nil { return i, err } // coalesce logs for later processing coalescedLogs = append(coalescedLogs, logs...) if err := WriteBlockReceipts(self.chainDb, block.Hash(), receipts); err != nil { return i, err } txcount += len(block.Transactions()) // write the block to the chain and get the status status, err := self.WriteBlock(block) if err != nil { return i, err } switch status { case CanonStatTy: if glog.V(logger.Debug) { glog.Infof("[%v] inserted block #%d (%d TXs %v G %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), block.GasUsed(), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) } events = append(events, ChainEvent{block, block.Hash(), logs}) // This puts transactions in a extra db for rpc if err := WriteTransactions(self.chainDb, block); err != nil { return i, err } // store the receipts if err := WriteReceipts(self.chainDb, receipts); err != nil { return i, err } // Write map map bloom filters if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil { return i, err } case SideStatTy: if glog.V(logger.Detail) { glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...). Took %v\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) } events = append(events, ChainSideEvent{block, logs}) case SplitStatTy: events = append(events, ChainSplitEvent{block, logs}) } stats.processed++ } if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) { tend := time.Since(tstart) start, end := chain[0], chain[len(chain)-1] glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", stats.processed, stats.queued, stats.ignored, txcount, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4]) } go self.postChainEvents(events, coalescedLogs) return 0, 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 { 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 } return block, nil }
// State returns a new mutable state based on the current HEAD block. func (self *BlockChain) State() (*state.StateDB, error) { return state.New(self.CurrentBlock().Root(), self.chainDb) }