func (self *XEth) AtStateNum(num int64) *XEth { var st *state.StateDB switch num { case -2: st = self.backend.Miner().PendingState().Copy() default: if block := self.getBlockByHeight(num); block != nil { st = state.New(block.Root(), self.backend.StateDb()) } else { st = state.New(self.backend.ChainManager().GetBlockByNumber(0).Root(), self.backend.StateDb()) } } return self.WithState(st) }
// 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 }
// Equivalent of the tx-pool state; updated by CheckTx and replaced on commit // For now, we just return the last block state func (app *EthereumApplication) ManagedState() *state.ManagedState { st, err := state.New(app.StateRoot(), app.ethereum.ChainDb()) if err != nil { return nil // (?!) } return state.ManageState(st) }
// 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 }
// 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) if cfg.State == nil { db, _ := ethdb.NewMemDatabase() cfg.State, _ = state.New(common.Hash{}, db) } var ( vmenv = NewEnv(cfg, cfg.State) sender = cfg.State.CreateAccount(cfg.Origin) receiver = cfg.State.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, ) return ret, cfg.State, err }
func TestTransactionChainFork(t *testing.T) { pool, key := setupTxPool() addr := crypto.PubkeyToAddress(key.PublicKey) resetState := func() { db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, db) pool.currentState = func() (*state.StateDB, error) { return statedb, nil } currentState, _ := pool.currentState() currentState.AddBalance(addr, big.NewInt(100000000000000)) pool.resetState() } resetState() tx := transaction(0, big.NewInt(100000), key) if err := pool.add(tx); err != nil { t.Error("didn't expect error", err) } pool.RemoveTransactions([]*types.Transaction{tx}) // reset the pool's internal state resetState() if err := pool.add(tx); err != nil { t.Error("didn't expect error", err) } }
func (self *XEth) LatestState() *XEth { st, err := state.New(self.StateRoot(), self.backend.ChainDb()) if err != nil { return nil } return self.WithState(st) }
// testBlockChainImport tries to process a chain of blocks, writing them into // the database if successful. func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { for _, block := range chain { // Try and process the block err := blockchain.Validator().ValidateBlock(block) if err != nil { if IsKnownBlockErr(err) { continue } return err } statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), blockchain.chainDb) if err != nil { return err } receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb) if err != nil { reportBlock(block, err) return err } err = blockchain.Validator().ValidateState(block, blockchain.GetBlock(block.ParentHash()), statedb, receipts, usedGas) if err != nil { reportBlock(block, err) return err } blockchain.mu.Lock() WriteTd(blockchain.chainDb, block.Hash(), new(big.Int).Add(block.Difficulty(), blockchain.GetTd(block.ParentHash()))) WriteBlock(blockchain.chainDb, block) statedb.Commit() blockchain.mu.Unlock() } return nil }
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) }
// 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 (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) }
// subscribes to new head block events and // waits until blockchain height is greater n at any time // given the current head, waits for the next chain event // sets the state to the current head // loop is async and quit by closing the channel // used in tests and JS console debug module to control advancing private chain manually // Note: this is not threadsafe, only called in JS single process and tests func (self *XEth) UpdateState() (wait chan *big.Int) { wait = make(chan *big.Int) go func() { sub := self.backend.EventMux().Subscribe(core.ChainHeadEvent{}) var m, n *big.Int var ok bool out: for { select { case event := <-sub.Chan(): ev, ok := event.(core.ChainHeadEvent) if ok { m = ev.Block.Number() if n != nil && n.Cmp(m) < 0 { wait <- n n = nil } statedb := state.New(ev.Block.Root(), self.backend.StateDb()) self.state = NewState(self, statedb) } case n, ok = <-wait: if !ok { break out } } } sub.Unsubscribe() }() return }
func TestTransactionDoubleNonce(t *testing.T) { pool, key := setupTxPool() addr := crypto.PubkeyToAddress(key.PublicKey) resetState := func() { db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) pool.currentState = func() *state.StateDB { return statedb } pool.currentState().AddBalance(addr, big.NewInt(100000000000000)) pool.resetState() } resetState() tx := transaction(0, big.NewInt(100000), key) tx2 := transaction(0, big.NewInt(1000000), key) if err := pool.add(tx); err != nil { t.Error("didn't expect error", err) } if err := pool.add(tx2); err != nil { t.Error("didn't expect error", err) } pool.checkQueue() if len(pool.pending) != 2 { t.Error("expected 2 pending txs. Got", len(pool.pending)) } }
// 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()) }
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) var m event.TypeMux key, _ := crypto.GenerateKey() return NewTxPool(&m, func() *state.StateDB { return statedb }, func() *big.Int { return big.NewInt(1000000) }), key }
// 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() }
// 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 }
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, db) var m event.TypeMux key, _ := crypto.GenerateKey() newPool := NewTxPool(testChainConfig(), &m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) newPool.resetState() return newPool, key }
// 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 }
// 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 }
// Actually make a block by simulating what miner would do // we seed chains by the first byte of the coinbase func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Database, seed int) *types.Block { var addr common.Address addr[0], addr[19] = byte(seed), byte(i) block := newBlockFromParent(addr, parent) state := state.New(block.Root(), db) cbase := state.GetOrNewStateObject(addr) cbase.SetGasPool(CalcGasLimit(parent)) cbase.AddBalance(BlockReward) state.Update() block.SetRoot(state.Root()) return block }
// SendTransaction implements ContractTransactor.SendTransaction, delegating the raw // transaction injection to the remote node. func (b *SimulatedBackend) SendTransaction(tx *types.Transaction) error { blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) { for _, tx := range b.pendingBlock.Transactions() { block.AddTx(tx) } block.AddTx(tx) }) b.pendingBlock = blocks[0] b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database) return nil }
// Create a new chain manager starting from given block // Effectively a fork factory func newChainManager(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager { genesis := GenesisBlock(db) bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux} bc.txState = state.ManageState(state.New(genesis.Root(), db)) bc.futureBlocks = NewBlockCache(1000) if block == nil { bc.Reset() } else { bc.currentBlock = block bc.td = block.Td } return bc }
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 }
// 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 }
// 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 run(ctx *cli.Context) { vm.Debug = ctx.GlobalBool(DebugFlag.Name) vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name) vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name) glog.SetToStderr(true) glog.SetV(ctx.GlobalInt(VerbosityFlag.Name)) db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, db) sender := statedb.CreateAccount(common.StringToAddress("sender")) receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))) vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name))) tstart := time.Now() ret, e := vmenv.Call( sender, receiver.Address(), common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), common.Big(ctx.GlobalString(GasFlag.Name)), common.Big(ctx.GlobalString(PriceFlag.Name)), common.Big(ctx.GlobalString(ValueFlag.Name)), ) vmdone := time.Since(tstart) if ctx.GlobalBool(DumpFlag.Name) { fmt.Println(string(statedb.Dump())) } vm.StdErrFormat(vmenv.StructLogs()) if ctx.GlobalBool(SysStatFlag.Name) { var mem runtime.MemStats runtime.ReadMemStats(&mem) fmt.Printf("vm took %v\n", vmdone) fmt.Printf(`alloc: %d tot alloc: %d no. malloc: %d heap alloc: %d heap objs: %d num gc: %d `, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC) } fmt.Printf("OUT: 0x%x", ret) if e != nil { fmt.Printf(" error: %v", e) } fmt.Println() }
// InsertPreState populates the given database with the genesis // accounts defined by the test. func (t *BlockTest) InsertPreState(db ethdb.Database, am *accounts.Manager) (*state.StateDB, error) { statedb, err := state.New(common.Hash{}, db) if err != nil { return nil, err } for addrString, acct := range t.preAccounts { addr, err := hex.DecodeString(addrString) if err != nil { return nil, err } code, err := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) if err != nil { return nil, err } balance, ok := new(big.Int).SetString(acct.Balance, 0) if !ok { return nil, err } nonce, err := strconv.ParseUint(prepInt(16, acct.Nonce), 16, 64) if err != nil { return nil, err } if acct.PrivateKey != "" { privkey, err := hex.DecodeString(strings.TrimPrefix(acct.PrivateKey, "0x")) err = crypto.ImportBlockTestKey(privkey) err = am.TimedUnlock(common.BytesToAddress(addr), "", 999999*time.Second) if err != nil { return nil, err } } obj := statedb.CreateAccount(common.HexToAddress(addrString)) obj.SetCode(code) obj.SetBalance(balance) obj.SetNonce(nonce) for k, v := range acct.Storage { statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v)) } } root, err := statedb.Commit() if err != nil { return nil, fmt.Errorf("error writing state: %v", err) } if t.Genesis.Root() != root { return nil, fmt.Errorf("computed state root does not match genesis block: genesis=%x computed=%x", t.Genesis.Root().Bytes()[:4], root.Bytes()[:4]) } return statedb, 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.Keccak256(codeb)) contentHash := common.HexToHash(contentHashHex) _, err = registrar.New(api.be).SetHashToHash(sender, codeHash, contentHash) return err == nil, err }
// 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 }