core, eth, miner, xeth: receipt storage fix
* Added GetReceiptsFromBlock, GetReceipt, PutReceipts * Added ContractAddress to receipt. See #1042
This commit is contained in:
parent
acd85fe95f
commit
2feb23c1da
|
@ -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)
|
||||||
|
|
||||||
bytes, err := rlp.EncodeToBytes(storageReceipts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
|
||||||
db.Put(append(receiptsPre, hash[:]...), bytes)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
Loading…
Reference in New Issue