core, eth, miner, xeth: receipt storage fix
* Added GetReceiptsFromBlock, GetReceipt, PutReceipts * Added ContractAddress to receipt. See #1042
This commit is contained in:
		| @@ -9,12 +9,12 @@ import ( | |||||||
| 	"github.com/ethereum/go-ethereum/common" | 	"github.com/ethereum/go-ethereum/common" | ||||||
| 	"github.com/ethereum/go-ethereum/core/state" | 	"github.com/ethereum/go-ethereum/core/state" | ||||||
| 	"github.com/ethereum/go-ethereum/core/types" | 	"github.com/ethereum/go-ethereum/core/types" | ||||||
|  | 	"github.com/ethereum/go-ethereum/crypto" | ||||||
| 	"github.com/ethereum/go-ethereum/event" | 	"github.com/ethereum/go-ethereum/event" | ||||||
| 	"github.com/ethereum/go-ethereum/logger" | 	"github.com/ethereum/go-ethereum/logger" | ||||||
| 	"github.com/ethereum/go-ethereum/logger/glog" | 	"github.com/ethereum/go-ethereum/logger/glog" | ||||||
| 	"github.com/ethereum/go-ethereum/params" | 	"github.com/ethereum/go-ethereum/params" | ||||||
| 	"github.com/ethereum/go-ethereum/pow" | 	"github.com/ethereum/go-ethereum/pow" | ||||||
| 	"github.com/ethereum/go-ethereum/rlp" |  | ||||||
| 	"gopkg.in/fatih/set.v0" | 	"gopkg.in/fatih/set.v0" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -24,8 +24,6 @@ const ( | |||||||
| 	BlockChainVersion = 3 | 	BlockChainVersion = 3 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var receiptsPre = []byte("receipts-") |  | ||||||
|  |  | ||||||
| type BlockProcessor struct { | type BlockProcessor struct { | ||||||
| 	db      common.Database | 	db      common.Database | ||||||
| 	extraDb common.Database | 	extraDb common.Database | ||||||
| @@ -83,6 +81,12 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated | |||||||
|  |  | ||||||
| 	usedGas.Add(usedGas, gas) | 	usedGas.Add(usedGas, gas) | ||||||
| 	receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas) | 	receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas) | ||||||
|  | 	receipt.TxHash = tx.Hash() | ||||||
|  | 	if MessageCreatesContract(tx) { | ||||||
|  | 		from, _ := tx.From() | ||||||
|  | 		receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	logs := statedb.GetLogs(tx.Hash()) | 	logs := statedb.GetLogs(tx.Hash()) | ||||||
| 	receipt.SetLogs(logs) | 	receipt.SetLogs(logs) | ||||||
| 	receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) | 	receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) | ||||||
| @@ -319,16 +323,20 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty | |||||||
| } | } | ||||||
|  |  | ||||||
| // GetBlockReceipts returns the receipts beloniging to the block hash | // GetBlockReceipts returns the receipts beloniging to the block hash | ||||||
| func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) { | func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts { | ||||||
| 	return getBlockReceipts(sm.extraDb, bhash) | 	if block := sm.ChainManager().GetBlock(bhash); block != nil { | ||||||
|  | 		return GetReceiptsFromBlock(sm.extraDb, block) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetLogs returns the logs of the given block. This method is using a two step approach | // 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 | // 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. | // the depricated way by re-processing the block. | ||||||
| func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { | func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { | ||||||
| 	receipts, err := sm.GetBlockReceipts(block.Hash()) | 	receipts := GetReceiptsFromBlock(sm.extraDb, block) | ||||||
| 	if err == nil && len(receipts) > 0 { | 	if len(receipts) > 0 { | ||||||
| 		// coalesce logs | 		// coalesce logs | ||||||
| 		for _, receipt := range receipts { | 		for _, receipt := range receipts { | ||||||
| 			logs = append(logs, receipt.Logs()...) | 			logs = append(logs, receipt.Logs()...) | ||||||
| @@ -391,15 +399,3 @@ func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, check | |||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) { |  | ||||||
| 	var rdata []byte |  | ||||||
| 	rdata, err = db.Get(append(receiptsPre, bhash[:]...)) |  | ||||||
|  |  | ||||||
| 	if err == nil { |  | ||||||
| 		err = rlp.DecodeBytes(rdata, &receipts) |  | ||||||
| 	} else { |  | ||||||
| 		glog.V(logger.Detail).Infof("getBlockReceipts error %v\n", err) |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -64,12 +64,9 @@ func TestPutReceipt(t *testing.T) { | |||||||
| 		Index:     0, | 		Index:     0, | ||||||
| 	}}) | 	}}) | ||||||
|  |  | ||||||
| 	PutReceipts(db, hash, types.Receipts{receipt}) | 	PutReceipts(db, types.Receipts{receipt}) | ||||||
| 	receipts, err := getBlockReceipts(db, hash) | 	receipt = GetReceipt(db, common.Hash{}) | ||||||
| 	if err != nil { | 	if receipt == nil { | ||||||
| 		t.Error("got err:", err) | 		t.Error("expected to get 1 receipt, got none.") | ||||||
| 	} |  | ||||||
| 	if len(receipts) != 1 { |  | ||||||
| 		t.Error("expected to get 1 receipt, got", len(receipts)) |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -632,7 +632,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { | |||||||
| 			// This puts transactions in a extra db for rpc | 			// This puts transactions in a extra db for rpc | ||||||
| 			PutTransactions(self.extraDb, block, block.Transactions()) | 			PutTransactions(self.extraDb, block, block.Transactions()) | ||||||
| 			// store the receipts | 			// store the receipts | ||||||
| 			PutReceipts(self.extraDb, block.Hash(), receipts) | 			PutReceipts(self.extraDb, receipts) | ||||||
| 		case SideStatTy: | 		case SideStatTy: | ||||||
| 			if glog.V(logger.Detail) { | 			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)) | 				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)) | ||||||
|   | |||||||
| @@ -8,6 +8,9 @@ import ( | |||||||
| 	"github.com/ethereum/go-ethereum/rlp" | 	"github.com/ethereum/go-ethereum/rlp" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var receiptsPre = []byte("receipts-") | ||||||
|  |  | ||||||
|  | // PutTransactions stores the transactions in the given database | ||||||
| func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { | func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { | ||||||
| 	for i, tx := range block.Transactions() { | 	for i, tx := range block.Transactions() { | ||||||
| 		rlpEnc, err := rlp.EncodeToBytes(tx) | 		rlpEnc, err := rlp.EncodeToBytes(tx) | ||||||
| @@ -34,18 +37,49 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func PutReceipts(db common.Database, hash common.Hash, receipts types.Receipts) error { | // PutReceipts stores the receipts in the current database | ||||||
| 	storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) | func PutReceipts(db common.Database, receipts types.Receipts) error { | ||||||
| 	for i, receipt := range receipts { | 	for _, receipt := range receipts { | ||||||
| 		storageReceipts[i] = (*types.ReceiptForStorage)(receipt) | 		storageReceipt := (*types.ReceiptForStorage)(receipt) | ||||||
|  | 		bytes, err := rlp.EncodeToBytes(storageReceipt) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bytes, err := rlp.EncodeToBytes(storageReceipts) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	db.Put(append(receiptsPre, hash[:]...), bytes) |  | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GetReceipt returns a receipt by hash | ||||||
|  | func GetReceipt(db common.Database, txHash common.Hash) *types.Receipt { | ||||||
|  | 	data, _ := db.Get(append(receiptsPre, txHash[:]...)) | ||||||
|  | 	if len(data) == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var receipt types.Receipt | ||||||
|  | 	err := rlp.DecodeBytes(data, &receipt) | ||||||
|  | 	if err != nil { | ||||||
|  | 		glog.V(logger.Error).Infoln("GetReceipt err:", err) | ||||||
|  | 	} | ||||||
|  | 	return &receipt | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetReceiptFromBlock returns all receipts with the given block | ||||||
|  | func GetReceiptsFromBlock(db common.Database, block *types.Block) types.Receipts { | ||||||
|  | 	// at some point we want: | ||||||
|  | 	//receipts := make(types.Receipts, len(block.Transactions())) | ||||||
|  | 	// but since we need to support legacy, we can't (yet) | ||||||
|  | 	var receipts types.Receipts | ||||||
|  | 	for _, tx := range block.Transactions() { | ||||||
|  | 		if receipt := GetReceipt(db, tx.Hash()); receipt != nil { | ||||||
|  | 			receipts = append(receipts, receipt) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return receipts | ||||||
|  | } | ||||||
|   | |||||||
| @@ -15,6 +15,8 @@ type Receipt struct { | |||||||
| 	PostState         []byte | 	PostState         []byte | ||||||
| 	CumulativeGasUsed *big.Int | 	CumulativeGasUsed *big.Int | ||||||
| 	Bloom             Bloom | 	Bloom             Bloom | ||||||
|  | 	TxHash            common.Hash | ||||||
|  | 	ContractAddress   common.Address | ||||||
| 	logs              state.Logs | 	logs              state.Logs | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -39,12 +41,14 @@ func (self *Receipt) DecodeRLP(s *rlp.Stream) error { | |||||||
| 		PostState         []byte | 		PostState         []byte | ||||||
| 		CumulativeGasUsed *big.Int | 		CumulativeGasUsed *big.Int | ||||||
| 		Bloom             Bloom | 		Bloom             Bloom | ||||||
|  | 		TxHash            common.Hash | ||||||
|  | 		ContractAddress   common.Address | ||||||
| 		Logs              state.Logs | 		Logs              state.Logs | ||||||
| 	} | 	} | ||||||
| 	if err := s.Decode(&r); err != nil { | 	if err := s.Decode(&r); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs = r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs | 	self.PostState, self.CumulativeGasUsed, self.Bloom, self.TxHash, self.ContractAddress, self.logs = r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, r.Logs | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -56,7 +60,7 @@ func (self *ReceiptForStorage) EncodeRLP(w io.Writer) error { | |||||||
| 	for i, log := range self.logs { | 	for i, log := range self.logs { | ||||||
| 		storageLogs[i] = (*state.LogForStorage)(log) | 		storageLogs[i] = (*state.LogForStorage)(log) | ||||||
| 	} | 	} | ||||||
| 	return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, storageLogs}) | 	return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.TxHash, self.ContractAddress, storageLogs}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *Receipt) RlpEncode() []byte { | func (self *Receipt) RlpEncode() []byte { | ||||||
|   | |||||||
| @@ -131,13 +131,10 @@ func (self *GasPriceOracle) processBlock(block *types.Block) { | |||||||
| // returns the lowers possible price with which a tx was or could have been included | // returns the lowers possible price with which a tx was or could have been included | ||||||
| func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int { | func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int { | ||||||
| 	gasUsed := new(big.Int) | 	gasUsed := new(big.Int) | ||||||
| 	recepits, err := self.eth.BlockProcessor().GetBlockReceipts(block.Hash()) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return self.eth.GpoMinGasPrice |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(recepits) > 0 { | 	receipts := self.eth.BlockProcessor().GetBlockReceipts(block.Hash()) | ||||||
| 		gasUsed = recepits[len(recepits)-1].CumulativeGasUsed | 	if len(receipts) > 0 { | ||||||
|  | 		gasUsed = receipts[len(receipts)-1].CumulativeGasUsed | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(), | 	if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(), | ||||||
|   | |||||||
| @@ -255,7 +255,7 @@ func (self *worker) wait() { | |||||||
| 				// This puts transactions in a extra db for rpc | 				// This puts transactions in a extra db for rpc | ||||||
| 				core.PutTransactions(self.extraDb, block, block.Transactions()) | 				core.PutTransactions(self.extraDb, block, block.Transactions()) | ||||||
| 				// store the receipts | 				// store the receipts | ||||||
| 				core.PutReceipts(self.extraDb, block.Hash(), self.current.receipts) | 				core.PutReceipts(self.extraDb, self.current.receipts) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			// check staleness and display confirmation | 			// check staleness and display confirmation | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								xeth/xeth.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								xeth/xeth.go
									
									
									
									
									
								
							| @@ -364,22 +364,12 @@ func (self *XEth) CurrentBlock() *types.Block { | |||||||
| 	return self.backend.ChainManager().CurrentBlock() | 	return self.backend.ChainManager().CurrentBlock() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *XEth) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) { | func (self *XEth) GetBlockReceipts(bhash common.Hash) types.Receipts { | ||||||
| 	return self.backend.BlockProcessor().GetBlockReceipts(bhash) | 	return self.backend.BlockProcessor().GetBlockReceipts(bhash) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *XEth) GetTxReceipt(txhash common.Hash) (receipt *types.Receipt, err error) { | func (self *XEth) GetTxReceipt(txhash common.Hash) *types.Receipt { | ||||||
| 	_, bhash, _, txi := self.EthTransactionByHash(common.ToHex(txhash[:])) | 	return core.GetReceipt(self.backend.ExtraDb(), txhash) | ||||||
| 	var receipts types.Receipts |  | ||||||
| 	receipts, err = self.backend.BlockProcessor().GetBlockReceipts(bhash) |  | ||||||
| 	if err == nil { |  | ||||||
| 		if txi < uint64(len(receipts)) { |  | ||||||
| 			receipt = receipts[txi] |  | ||||||
| 		} else { |  | ||||||
| 			err = fmt.Errorf("Invalid tx index") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *XEth) GasLimit() *big.Int { | func (self *XEth) GasLimit() *big.Int { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user