block_processor.go 12.8 KB
Newer Older
1
// Copyright 2014 The go-ethereum Authors
2
// This file is part of the go-ethereum library.
3
//
4
// The go-ethereum library is free software: you can redistribute it and/or modify
5 6 7 8
// 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.
//
9
// The go-ethereum library is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 13 14
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
15
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16

obscuren's avatar
obscuren committed
17
package core
obscuren's avatar
obscuren committed
18 19

import (
obscuren's avatar
obscuren committed
20
	"fmt"
obscuren's avatar
obscuren committed
21 22
	"math/big"
	"sync"
obscuren's avatar
obscuren committed
23
	"time"
obscuren's avatar
obscuren committed
24

obscuren's avatar
obscuren committed
25
	"github.com/ethereum/go-ethereum/common"
obscuren's avatar
obscuren committed
26
	"github.com/ethereum/go-ethereum/core/state"
obscuren's avatar
obscuren committed
27
	"github.com/ethereum/go-ethereum/core/types"
28
	"github.com/ethereum/go-ethereum/crypto"
29
	"github.com/ethereum/go-ethereum/event"
obscuren's avatar
obscuren committed
30
	"github.com/ethereum/go-ethereum/logger"
obscuren's avatar
obscuren committed
31
	"github.com/ethereum/go-ethereum/logger/glog"
32
	"github.com/ethereum/go-ethereum/params"
obscuren's avatar
obscuren committed
33
	"github.com/ethereum/go-ethereum/pow"
34
	"gopkg.in/fatih/set.v0"
obscuren's avatar
obscuren committed
35 36
)

37 38 39
const (
	// must be bumped when consensus algorithm is changed, this forces the upgradedb
	// command to be run (forces the blocks to be imported again using the new algorithm)
40
	BlockChainVersion = 3
41 42
)

43
type BlockProcessor struct {
44
	chainDb common.Database
obscuren's avatar
obscuren committed
45 46
	// Mutex for locking the block processor. Blocks can only be handled one at a time
	mutex sync.Mutex
47
	// Canonical block chain
48
	bc *ChainManager
obscuren's avatar
obscuren committed
49 50
	// non-persistent key/value memory storage
	mem map[string]*big.Int
obscuren's avatar
obscuren committed
51
	// Proof of work used for validating
obscuren's avatar
obscuren committed
52
	Pow pow.PoW
53

54
	events event.Subscription
obscuren's avatar
obscuren committed
55 56

	eventMux *event.TypeMux
obscuren's avatar
obscuren committed
57 58
}

59 60 61 62 63 64 65 66 67 68 69 70
// TODO: type GasPool big.Int
//
// GasPool is implemented by state.StateObject. This is a historical
// coincidence. Gas tracking should move out of StateObject.

// GasPool tracks the amount of gas available during
// execution of the transactions in a block.
type GasPool interface {
	AddGas(gas, price *big.Int)
	SubGas(gas, price *big.Int) error
}

71
func NewBlockProcessor(db common.Database, pow pow.PoW, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
72
	sm := &BlockProcessor{
73
		chainDb:  db,
obscuren's avatar
obscuren committed
74
		mem:      make(map[string]*big.Int),
obscuren's avatar
obscuren committed
75
		Pow:      pow,
76 77
		bc:       chainManager,
		eventMux: eventMux,
obscuren's avatar
obscuren committed
78
	}
79
	return sm
obscuren's avatar
obscuren committed
80 81
}

82
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
83 84
	gp := statedb.GetOrNewStateObject(block.Coinbase())
	gp.SetGasLimit(block.GasLimit())
obscuren's avatar
obscuren committed
85

86
	// Process the transactions on to parent state
87
	receipts, err = sm.ApplyTransactions(gp, statedb, block, block.Transactions(), transientProcess)
obscuren's avatar
obscuren committed
88 89 90 91 92 93 94
	if err != nil {
		return nil, err
	}

	return receipts, nil
}

95 96
func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
	_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, gp)
97
	if err != nil {
98 99
		return nil, nil, err
	}
obscuren's avatar
obscuren committed
100 101

	// Update the state with pending changes
102
	statedb.SyncIntermediate()
obscuren's avatar
obscuren committed
103

104 105
	usedGas.Add(usedGas, gas)
	receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas)
106
	receipt.TxHash = tx.Hash()
107
	receipt.GasUsed = new(big.Int).Set(gas)
108 109 110 111 112
	if MessageCreatesContract(tx) {
		from, _ := tx.From()
		receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce())
	}

113 114
	logs := statedb.GetLogs(tx.Hash())
	receipt.SetLogs(logs)
obscuren's avatar
obscuren committed
115
	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
obscuren's avatar
obscuren committed
116 117

	glog.V(logger.Debug).Infoln(receipt)
obscuren's avatar
obscuren committed
118 119 120 121

	// Notify all subscribers
	if !transientProcess {
		go self.eventMux.Post(TxPostEvent{tx})
obscuren's avatar
obscuren committed
122
		go self.eventMux.Post(logs)
obscuren's avatar
obscuren committed
123 124
	}

125
	return receipt, gas, err
obscuren's avatar
obscuren committed
126
}
127 128 129
func (self *BlockProcessor) ChainManager() *ChainManager {
	return self.bc
}
obscuren's avatar
obscuren committed
130

131
func (self *BlockProcessor) ApplyTransactions(gp GasPool, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, error) {
132
	var (
133 134 135 136
		receipts      types.Receipts
		totalUsedGas  = big.NewInt(0)
		err           error
		cumulativeSum = new(big.Int)
137
		header        = block.Header()
138 139
	)

140 141 142
	for i, tx := range txs {
		statedb.StartRecord(tx.Hash(), block.Hash(), i)

143
		receipt, txGas, err := self.ApplyTransaction(gp, statedb, header, tx, totalUsedGas, transientProcess)
144
		if err != nil {
145
			return nil, err
146 147
		}

obscuren's avatar
obscuren committed
148
		if err != nil {
obscuren's avatar
obscuren committed
149
			glog.V(logger.Core).Infoln("TX err:", err)
obscuren's avatar
obscuren committed
150 151
		}
		receipts = append(receipts, receipt)
152

obscuren's avatar
obscuren committed
153
		cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice()))
obscuren's avatar
obscuren committed
154
	}
obscuren's avatar
obscuren committed
155

156 157 158
	if block.GasUsed().Cmp(totalUsedGas) != 0 {
		return nil, ValidationError(fmt.Sprintf("gas used error (%v / %v)", block.GasUsed(), totalUsedGas))
	}
Maran's avatar
Maran committed
159

obscuren's avatar
obscuren committed
160
	if transientProcess {
161
		go self.eventMux.Post(PendingBlockEvent{block, statedb.Logs()})
obscuren's avatar
obscuren committed
162 163
	}

164
	return receipts, err
obscuren's avatar
obscuren committed
165 166
}

167 168 169 170 171
func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err error) {
	// Processing a blocks may never happen simultaneously
	sm.mutex.Lock()
	defer sm.mutex.Unlock()

172 173
	if !sm.bc.HasBlock(block.ParentHash()) {
		return nil, ParentError(block.ParentHash())
174
	}
175
	parent := sm.bc.GetBlock(block.ParentHash())
176 177 178 179 180

	// FIXME Change to full header validation. See #1225
	errch := make(chan bool)
	go func() { errch <- sm.Pow.Verify(block) }()

181
	logs, _, err = sm.processWithParent(block, parent)
182
	if !<-errch {
183 184
		return nil, ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
	}
185

186
	return logs, err
187 188
}

189 190 191
// 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.
192
func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, receipts types.Receipts, err error) {
obscuren's avatar
obscuren committed
193
	// Processing a blocks may never happen simultaneously
194 195
	sm.mutex.Lock()
	defer sm.mutex.Unlock()
obscuren's avatar
obscuren committed
196

197
	if sm.bc.HasBlock(block.Hash()) {
198
		return nil, nil, &KnownBlockError{block.Number(), block.Hash()}
obscuren's avatar
obscuren committed
199 200
	}

201
	if !sm.bc.HasBlock(block.ParentHash()) {
202
		return nil, nil, ParentError(block.ParentHash())
obscuren's avatar
obscuren committed
203
	}
204
	parent := sm.bc.GetBlock(block.ParentHash())
205
	return sm.processWithParent(block, parent)
206
}
obscuren's avatar
obscuren committed
207

208
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, receipts types.Receipts, err error) {
209
	// Create a new state based on the parent's root (e.g., create copy)
210
	state := state.New(parent.Root(), sm.chainDb)
211 212 213
	header := block.Header()
	uncles := block.Uncles()
	txs := block.Transactions()
obscuren's avatar
obscuren committed
214

215
	// Block validation
216
	if err = ValidateHeader(sm.Pow, header, parent, false, false); err != nil {
obscuren's avatar
obscuren committed
217
		return
218 219
	}

obscuren's avatar
obscuren committed
220
	// There can be at most two uncles
221
	if len(uncles) > 2 {
222
		return nil, nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles))
obscuren's avatar
obscuren committed
223 224
	}

225
	receipts, err = sm.TransitionState(state, parent, block, false)
226
	if err != nil {
227
		return
228 229
	}

230 231
	// Validate the received block's bloom with the one derived from the generated receipts.
	// For valid blocks this should always validate to true.
232
	rbloom := types.CreateBloom(receipts)
obscuren's avatar
obscuren committed
233
	if rbloom != header.Bloom {
234 235 236 237
		err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
		return
	}

238
	// The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]]))
239
	// can be used by light clients to make sure they've received the correct Txs
240
	txSha := types.DeriveSha(txs)
obscuren's avatar
obscuren committed
241
	if txSha != header.TxHash {
242
		err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha)
obscuren's avatar
obscuren committed
243 244
		return
	}
obscuren's avatar
obscuren committed
245

246
	// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
247
	receiptSha := types.DeriveSha(receipts)
obscuren's avatar
obscuren committed
248
	if receiptSha != header.ReceiptHash {
249 250 251 252 253
		err = fmt.Errorf("invalid receipt root hash. received=%x calculated=%x", header.ReceiptHash, receiptSha)
		return
	}

	// Verify UncleHash before running other uncle validations
254
	unclesSha := types.CalcUncleHash(uncles)
255 256
	if unclesSha != header.UncleHash {
		err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha)
257 258
		return
	}
obscuren's avatar
obscuren committed
259

obscuren's avatar
obscuren committed
260 261
	// Verify uncles
	if err = sm.VerifyUncles(state, block, parent); err != nil {
262
		return
obscuren's avatar
obscuren committed
263
	}
obscuren's avatar
obscuren committed
264
	// Accumulate static rewards; block reward, uncle's and uncle inclusion.
265
	AccumulateRewards(state, header, uncles)
obscuren's avatar
obscuren committed
266

267 268
	// Commit state objects/accounts to a temporary trie (does not save)
	// used to calculate the state root.
269
	state.SyncObjects()
obscuren's avatar
obscuren committed
270
	if header.Root != state.Root() {
271
		err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
272
		return
obscuren's avatar
obscuren committed
273 274
	}

obscuren's avatar
obscuren committed
275
	// Sync the current block's state to the database
276
	state.Sync()
obscuren's avatar
obscuren committed
277

278
	return state.Logs(), receipts, nil
obscuren's avatar
obscuren committed
279 280
}

281 282 283 284 285
var (
	big8  = big.NewInt(8)
	big32 = big.NewInt(32)
)

286 287
// AccumulateRewards credits the coinbase of the given block with the
// mining reward. The total reward consists of the static block reward
288 289
// and rewards for included uncles. The coinbase of each uncle block is
// also rewarded.
290 291
func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*types.Header) {
	reward := new(big.Int).Set(BlockReward)
292
	r := new(big.Int)
293
	for _, uncle := range uncles {
294 295 296 297
		r.Add(uncle.Number, big8)
		r.Sub(r, header.Number)
		r.Mul(r, BlockReward)
		r.Div(r, big8)
298 299
		statedb.AddBalance(uncle.Coinbase, r)

300 301
		r.Div(BlockReward, big32)
		reward.Add(reward, r)
302 303 304 305
	}
	statedb.AddBalance(header.Coinbase, reward)
}

obscuren's avatar
obscuren committed
306
func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error {
307
	uncles := set.New()
308
	ancestors := make(map[common.Hash]*types.Block)
309
	for _, ancestor := range sm.bc.GetBlocksFromHash(block.ParentHash(), 7) {
310
		ancestors[ancestor.Hash()] = ancestor
obscuren's avatar
obscuren committed
311 312
		// Include ancestors uncles in the uncle set. Uncles must be unique.
		for _, uncle := range ancestor.Uncles() {
313
			uncles.Add(uncle.Hash())
obscuren's avatar
obscuren committed
314
		}
315
	}
316
	ancestors[block.Hash()] = block
317
	uncles.Add(block.Hash())
318

319
	for i, uncle := range block.Uncles() {
320
		hash := uncle.Hash()
321
		if uncles.Has(hash) {
obscuren's avatar
obscuren committed
322
			// Error not unique
323
			return UncleError("uncle[%d](%x) not unique", i, hash[:4])
obscuren's avatar
obscuren committed
324
		}
325
		uncles.Add(hash)
obscuren's avatar
obscuren committed
326

327
		if ancestors[hash] != nil {
328
			branch := fmt.Sprintf("  O - %x\n  |\n", block.Hash())
329 330 331
			for h := range ancestors {
				branch += fmt.Sprintf("  O - %x\n  |\n", h)
			}
obscuren's avatar
obscuren committed
332
			glog.Infoln(branch)
333
			return UncleError("uncle[%d](%x) is ancestor", i, hash[:4])
obscuren's avatar
obscuren committed
334 335
		}

336
		if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == parent.Hash() {
Gustav Simonsson's avatar
Gustav Simonsson committed
337
			return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
obscuren's avatar
obscuren committed
338
		}
obscuren's avatar
obscuren committed
339

340
		if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
341
			return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
obscuren's avatar
obscuren committed
342
		}
obscuren's avatar
obscuren committed
343
	}
obscuren's avatar
obscuren committed
344 345 346 347

	return nil
}

348
// GetBlockReceipts returns the receipts beloniging to the block hash
349 350
func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts {
	if block := sm.ChainManager().GetBlock(bhash); block != nil {
351
		return GetBlockReceipts(sm.chainDb, block.Hash())
352 353 354
	}

	return nil
355 356 357 358 359
}

// GetLogs returns the logs of the given block. This method is using a two step approach
// where it tries to get it from the (updated) method which gets them from the receipts or
// the depricated way by re-processing the block.
obscuren's avatar
obscuren committed
360
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
361
	receipts := GetBlockReceipts(sm.chainDb, block.Hash())
362 363 364
	// coalesce logs
	for _, receipt := range receipts {
		logs = append(logs, receipt.Logs()...)
obscuren's avatar
obscuren committed
365
	}
366
	return logs, nil
obscuren's avatar
obscuren committed
367
}
368

369 370
// See YP section 4.3.4. "Block Header Validity"
// Validates a block. Returns an error if the block is invalid.
371
func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, checkPow, uncle bool) error {
372 373 374 375
	if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
		return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
	}

376 377 378 379 380 381 382 383
	if uncle {
		if block.Time.Cmp(common.MaxBig) == 1 {
			return BlockTSTooBigErr
		}
	} else {
		if block.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 {
			return BlockFutureErr
		}
384
	}
385
	if block.Time.Cmp(parent.Time()) != 1 {
386 387 388
		return BlockEqualTSErr
	}

389
	expd := CalcDifficulty(block.Time.Uint64(), parent.Time().Uint64(), parent.Number(), parent.Difficulty())
390 391 392 393
	if expd.Cmp(block.Difficulty) != 0 {
		return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
	}

394 395 396
	var a, b *big.Int
	a = parent.GasLimit()
	a = a.Sub(a, block.GasLimit)
397
	a.Abs(a)
398 399
	b = parent.GasLimit()
	b = b.Div(b, params.GasLimitBoundDivisor)
400 401 402 403
	if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) {
		return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
	}

404 405 406
	num := parent.Number()
	num.Sub(block.Number, num)
	if num.Cmp(big.NewInt(1)) != 0 {
407 408 409 410 411 412 413 414 415 416 417 418
		return BlockNumberErr
	}

	if checkPow {
		// Verify the nonce of the block. Return an error if it's not valid
		if !pow.Verify(types.NewBlockWithHeader(block)) {
			return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
		}
	}

	return nil
}