| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // 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. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | package core | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 	"github.com/syndtr/goleveldb/leveldb" | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:18:09 +02:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	receiptsPre      = []byte("receipts-") | 
					
						
							|  |  |  | 	blockReceiptsPre = []byte("receipts-block-") | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // PutTransactions stores the transactions in the given database | 
					
						
							| 
									
										
										
										
											2015-09-14 09:35:57 +02:00
										 |  |  | func PutTransactions(db ethdb.Database, block *types.Block, txs types.Transactions) { | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 	batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 	_, batchWrite := db.(*ethdb.LDBDatabase) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 	for i, tx := range block.Transactions() { | 
					
						
							|  |  |  | 		rlpEnc, err := rlp.EncodeToBytes(tx) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			glog.V(logger.Debug).Infoln("Failed encoding tx", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if batchWrite { | 
					
						
							|  |  |  | 			batch.Put(tx.Hash().Bytes(), rlpEnc) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			db.Put(tx.Hash().Bytes(), rlpEnc) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var txExtra struct { | 
					
						
							|  |  |  | 			BlockHash  common.Hash | 
					
						
							|  |  |  | 			BlockIndex uint64 | 
					
						
							|  |  |  | 			Index      uint64 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		txExtra.BlockHash = block.Hash() | 
					
						
							|  |  |  | 		txExtra.BlockIndex = block.NumberU64() | 
					
						
							|  |  |  | 		txExtra.Index = uint64(i) | 
					
						
							|  |  |  | 		rlpMeta, err := rlp.EncodeToBytes(txExtra) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if batchWrite { | 
					
						
							|  |  |  | 			batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if db, ok := db.(*ethdb.LDBDatabase); ok { | 
					
						
							|  |  |  | 		if err := db.LDB().Write(batch, nil); err != nil { | 
					
						
							|  |  |  | 			glog.V(logger.Error).Infoln("db write err:", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | func DeleteTransaction(db ethdb.Database, txHash common.Hash) { | 
					
						
							|  |  |  | 	db.Delete(txHash[:]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func GetTransaction(db ethdb.Database, txhash common.Hash) *types.Transaction { | 
					
						
							|  |  |  | 	data, _ := db.Get(txhash[:]) | 
					
						
							|  |  |  | 	if len(data) != 0 { | 
					
						
							|  |  |  | 		var tx types.Transaction | 
					
						
							|  |  |  | 		if err := rlp.DecodeBytes(data, &tx); err != nil { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return &tx | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | // PutReceipts stores the receipts in the current database | 
					
						
							| 
									
										
										
										
											2015-09-14 09:35:57 +02:00
										 |  |  | func PutReceipts(db ethdb.Database, receipts types.Receipts) error { | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 	batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 	_, batchWrite := db.(*ethdb.LDBDatabase) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 	for _, receipt := range receipts { | 
					
						
							|  |  |  | 		storageReceipt := (*types.ReceiptForStorage)(receipt) | 
					
						
							|  |  |  | 		bytes, err := rlp.EncodeToBytes(storageReceipt) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-17 15:43:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if batchWrite { | 
					
						
							|  |  |  | 			batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if db, ok := db.(*ethdb.LDBDatabase); ok { | 
					
						
							|  |  |  | 		if err := db.LDB().Write(batch, nil); err != nil { | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | // Delete a receipts from the database | 
					
						
							|  |  |  | func DeleteReceipt(db ethdb.Database, txHash common.Hash) { | 
					
						
							|  |  |  | 	db.Delete(append(receiptsPre, txHash[:]...)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | // GetReceipt returns a receipt by hash | 
					
						
							| 
									
										
										
										
											2015-09-14 09:35:57 +02:00
										 |  |  | func GetReceipt(db ethdb.Database, txHash common.Hash) *types.Receipt { | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 	data, _ := db.Get(append(receiptsPre, txHash[:]...)) | 
					
						
							|  |  |  | 	if len(data) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 	var receipt types.Receipt | 
					
						
							|  |  |  | 	err := rlp.DecodeBytes(data, &receipt) | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-07-06 20:59:12 +02:00
										 |  |  | 		glog.V(logger.Core).Infoln("GetReceipt err:", err) | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 	return &receipt | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:18:09 +02:00
										 |  |  | // GetBlockReceipts returns the receipts generated by the transactions | 
					
						
							|  |  |  | // included in block's given hash. | 
					
						
							| 
									
										
										
										
											2015-09-14 09:35:57 +02:00
										 |  |  | func GetBlockReceipts(db ethdb.Database, hash common.Hash) types.Receipts { | 
					
						
							| 
									
										
										
										
											2015-07-14 18:18:09 +02:00
										 |  |  | 	data, _ := db.Get(append(blockReceiptsPre, hash[:]...)) | 
					
						
							|  |  |  | 	if len(data) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:18:09 +02:00
										 |  |  | 	var receipts types.Receipts | 
					
						
							|  |  |  | 	err := rlp.DecodeBytes(data, &receipts) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Core).Infoln("GetReceiptse err", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-04 02:25:04 +02:00
										 |  |  | 	return receipts | 
					
						
							| 
									
										
										
										
											2015-07-03 11:24:42 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-14 18:18:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // PutBlockReceipts stores the block's transactions associated receipts | 
					
						
							|  |  |  | // and stores them by block hash in a single slice. This is required for | 
					
						
							|  |  |  | // forks and chain reorgs | 
					
						
							| 
									
										
										
										
											2015-09-14 09:35:57 +02:00
										 |  |  | func PutBlockReceipts(db ethdb.Database, block *types.Block, receipts types.Receipts) error { | 
					
						
							| 
									
										
										
										
											2015-07-14 18:18:09 +02:00
										 |  |  | 	rs := make([]*types.ReceiptForStorage, len(receipts)) | 
					
						
							|  |  |  | 	for i, receipt := range receipts { | 
					
						
							|  |  |  | 		rs[i] = (*types.ReceiptForStorage)(receipt) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	bytes, err := rlp.EncodeToBytes(rs) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hash := block.Hash() | 
					
						
							|  |  |  | 	err = db.Put(append(blockReceiptsPre, hash[:]...), bytes) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |