chain_makers.go 6.71 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.

17 18 19
package core

import (
obscuren's avatar
obscuren committed
20 21
	"math/big"

obscuren's avatar
obscuren committed
22
	"github.com/ethereum/go-ethereum/common"
obscuren's avatar
obscuren committed
23
	"github.com/ethereum/go-ethereum/core/state"
obscuren's avatar
obscuren committed
24
	"github.com/ethereum/go-ethereum/core/types"
25 26 27 28
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/pow"
)

29 30
// FakePow is a non-validating proof of work implementation.
// It returns true from Verify for any block.
31 32
type FakePow struct{}

33 34
func (f FakePow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) {
	return 0, nil
35 36 37 38 39 40 41
}
func (f FakePow) Verify(block pow.Block) bool { return true }
func (f FakePow) GetHashrate() int64          { return 0 }
func (f FakePow) Turbo(bool)                  {}

// So we can deterministically seed different blockchains
var (
42 43
	canonicalSeed = 1
	forkSeed      = 2
44
)
45

46 47 48 49 50 51 52 53 54 55 56 57 58
// BlockGen creates blocks for testing.
// See GenerateChain for a detailed explanation.
type BlockGen struct {
	i       int
	parent  *types.Block
	chain   []*types.Block
	header  *types.Header
	statedb *state.StateDB

	coinbase *state.StateObject
	txs      []*types.Transaction
	receipts []*types.Receipt
	uncles   []*types.Header
59 60
}

61 62 63 64 65 66 67 68 69 70 71 72
// SetCoinbase sets the coinbase of the generated block.
// It can be called at most once.
func (b *BlockGen) SetCoinbase(addr common.Address) {
	if b.coinbase != nil {
		if len(b.txs) > 0 {
			panic("coinbase must be set before adding transactions")
		}
		panic("coinbase can only be set once")
	}
	b.header.Coinbase = addr
	b.coinbase = b.statedb.GetOrNewStateObject(addr)
	b.coinbase.SetGasLimit(b.header.GasLimit)
73 74
}

75 76 77
// SetExtra sets the extra data field of the generated block.
func (b *BlockGen) SetExtra(data []byte) {
	b.header.Extra = data
78 79
}

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
// AddTx adds a transaction to the generated block. If no coinbase has
// been set, the block's coinbase is set to the zero address.
//
// AddTx panics if the transaction cannot be executed. In addition to
// the protocol-imposed limitations (gas limit, etc.), there are some
// further limitations on the content of transactions that can be
// added. Notably, contract code relying on the BLOCKHASH instruction
// will panic during execution.
func (b *BlockGen) AddTx(tx *types.Transaction) {
	if b.coinbase == nil {
		b.SetCoinbase(common.Address{})
	}
	_, gas, err := ApplyMessage(NewEnv(b.statedb, nil, tx, b.header), tx, b.coinbase)
	if err != nil {
		panic(err)
	}
96
	b.statedb.SyncIntermediate()
97 98 99 100 101 102 103
	b.header.GasUsed.Add(b.header.GasUsed, gas)
	receipt := types.NewReceipt(b.statedb.Root().Bytes(), b.header.GasUsed)
	logs := b.statedb.GetLogs(tx.Hash())
	receipt.SetLogs(logs)
	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
	b.txs = append(b.txs, tx)
	b.receipts = append(b.receipts, receipt)
104 105
}

106 107 108 109 110 111 112
// TxNonce returns the next valid transaction nonce for the
// account at addr. It panics if the account does not exist.
func (b *BlockGen) TxNonce(addr common.Address) uint64 {
	if !b.statedb.HasAccount(addr) {
		panic("account does not exist")
	}
	return b.statedb.GetNonce(addr)
113 114
}

115 116 117 118
// AddUncle adds an uncle header to the generated block.
func (b *BlockGen) AddUncle(h *types.Header) {
	b.uncles = append(b.uncles, h)
}
119

120 121 122 123 124 125
// PrevBlock returns a previously generated block by number. It panics if
// num is greater or equal to the number of the block being generated.
// For index -1, PrevBlock returns the parent block given to GenerateChain.
func (b *BlockGen) PrevBlock(index int) *types.Block {
	if index >= b.i {
		panic("block index out of range")
126
	}
127 128 129 130
	if index == -1 {
		return b.parent
	}
	return b.chain[index]
131 132
}

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
// 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 common.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)
152
		}
153
		AccumulateRewards(statedb, h, b.uncles)
154
		statedb.SyncIntermediate()
155 156 157 158 159 160
		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)
obscuren's avatar
obscuren committed
161
		block.Td = CalcTD(block, parent)
162 163 164 165 166 167
		blocks[i] = block
		parent = block
	}
	return blocks
}

168 169 170 171 172 173
func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
	time := parent.Time() + 10 // block time is fixed at 10 seconds
	return &types.Header{
		Root:       state.Root(),
		ParentHash: parent.Hash(),
		Coinbase:   parent.Coinbase(),
174
		Difficulty: CalcDifficulty(time, parent.Time(), parent.Difficulty()),
175 176 177 178
		GasLimit:   CalcGasLimit(parent),
		GasUsed:    new(big.Int),
		Number:     new(big.Int).Add(parent.Number(), common.Big1),
		Time:       uint64(time),
179 180 181
	}
}

182 183
// newCanonical creates a new deterministic canonical chain by running
// InsertChain on the result of makeChain.
obscuren's avatar
obscuren committed
184
func newCanonical(n int, db common.Database) (*BlockProcessor, error) {
185
	evmux := &event.TypeMux{}
186 187 188

	WriteTestNetGenesisBlock(db, db, 0)
	chainman, _ := NewChainManager(db, db, db, FakePow{}, evmux)
189
	bman := NewBlockProcessor(db, db, FakePow{}, chainman, evmux)
190 191 192 193 194
	bman.bc.SetProcessor(bman)
	parent := bman.bc.CurrentBlock()
	if n == 0 {
		return bman, nil
	}
195
	lchain := makeChain(parent, n, db, canonicalSeed)
196
	_, err := bman.bc.InsertChain(lchain)
197
	return bman, err
198
}
199 200 201 202 203 204

func makeChain(parent *types.Block, n int, db common.Database, seed int) []*types.Block {
	return GenerateChain(parent, db, n, func(i int, b *BlockGen) {
		b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
	})
}